1 /* 2 * Copyright (C) 2016 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.incallui.contactgrid; 18 19 import android.content.Context; 20 import android.support.annotation.Nullable; 21 import android.telephony.PhoneNumberUtils; 22 import android.text.BidiFormatter; 23 import android.text.TextDirectionHeuristics; 24 import android.text.TextUtils; 25 import com.android.incallui.call.DialerCall.State; 26 import com.android.incallui.incall.protocol.PrimaryCallState; 27 import com.android.incallui.incall.protocol.PrimaryInfo; 28 29 /** 30 * Gets the content of the bottom row. For example: 31 * 32 * <ul> 33 * <li>Mobile +1 (650) 253-0000 34 * <li>[HD attempting icon]/[HD icon] 00:15 35 * <li>Call ended 36 * <li>Hanging up 37 * </ul> 38 */ 39 public class BottomRow { 40 41 /** Content of the bottom row. */ 42 public static class Info { 43 44 @Nullable public final CharSequence label; 45 public final boolean isTimerVisible; 46 public final boolean isWorkIconVisible; 47 public final boolean isHdAttemptingIconVisible; 48 public final boolean isHdIconVisible; 49 public final boolean isForwardIconVisible; 50 public final boolean isSpamIconVisible; 51 public final boolean shouldPopulateAccessibilityEvent; 52 53 public Info( 54 @Nullable CharSequence label, 55 boolean isTimerVisible, 56 boolean isWorkIconVisible, 57 boolean isHdAttemptingIconVisible, 58 boolean isHdIconVisible, 59 boolean isForwardIconVisible, 60 boolean isSpamIconVisible, 61 boolean shouldPopulateAccessibilityEvent) { 62 this.label = label; 63 this.isTimerVisible = isTimerVisible; 64 this.isWorkIconVisible = isWorkIconVisible; 65 this.isHdAttemptingIconVisible = isHdAttemptingIconVisible; 66 this.isHdIconVisible = isHdIconVisible; 67 this.isForwardIconVisible = isForwardIconVisible; 68 this.isSpamIconVisible = isSpamIconVisible; 69 this.shouldPopulateAccessibilityEvent = shouldPopulateAccessibilityEvent; 70 } 71 } 72 73 private BottomRow() {} 74 75 public static Info getInfo(Context context, PrimaryCallState state, PrimaryInfo primaryInfo) { 76 CharSequence label; 77 boolean isTimerVisible = state.state() == State.ACTIVE; 78 boolean isForwardIconVisible = state.isForwardedNumber(); 79 boolean isWorkIconVisible = state.isWorkCall(); 80 boolean isHdIconVisible = state.isHdAudioCall() && !isForwardIconVisible; 81 boolean isHdAttemptingIconVisible = state.isHdAttempting(); 82 boolean isSpamIconVisible = false; 83 boolean shouldPopulateAccessibilityEvent = true; 84 85 if (isIncoming(state) && primaryInfo.isSpam()) { 86 label = context.getString(R.string.contact_grid_incoming_suspected_spam); 87 isSpamIconVisible = true; 88 isHdIconVisible = false; 89 } else if (state.state() == State.DISCONNECTING) { 90 // While in the DISCONNECTING state we display a "Hanging up" message in order to make the UI 91 // feel more responsive. (In GSM it's normal to see a delay of a couple of seconds while 92 // negotiating the disconnect with the network, so the "Hanging up" state at least lets the 93 // user know that we're doing something. This state is currently not used with CDMA.) 94 label = context.getString(R.string.incall_hanging_up); 95 } else if (state.state() == State.DISCONNECTED) { 96 label = state.disconnectCause().getLabel(); 97 if (TextUtils.isEmpty(label)) { 98 label = context.getString(R.string.incall_call_ended); 99 } 100 } else { 101 label = getLabelForPhoneNumber(primaryInfo); 102 shouldPopulateAccessibilityEvent = primaryInfo.nameIsNumber(); 103 } 104 105 return new Info( 106 label, 107 isTimerVisible, 108 isWorkIconVisible, 109 isHdAttemptingIconVisible, 110 isHdIconVisible, 111 isForwardIconVisible, 112 isSpamIconVisible, 113 shouldPopulateAccessibilityEvent); 114 } 115 116 private static CharSequence getLabelForPhoneNumber(PrimaryInfo primaryInfo) { 117 if (primaryInfo.location() != null) { 118 return primaryInfo.location(); 119 } 120 if (!primaryInfo.nameIsNumber() && !TextUtils.isEmpty(primaryInfo.number())) { 121 CharSequence spannedNumber = spanDisplayNumber(primaryInfo.number()); 122 if (primaryInfo.label() == null) { 123 return spannedNumber; 124 } else { 125 return TextUtils.concat(primaryInfo.label(), " ", spannedNumber); 126 } 127 } 128 return null; 129 } 130 131 private static CharSequence spanDisplayNumber(String displayNumber) { 132 return PhoneNumberUtils.createTtsSpannable( 133 BidiFormatter.getInstance().unicodeWrap(displayNumber, TextDirectionHeuristics.LTR)); 134 } 135 136 private static boolean isIncoming(PrimaryCallState state) { 137 return state.state() == State.INCOMING || state.state() == State.CALL_WAITING; 138 } 139 } 140