Home | History | Annotate | Download | only in contactgrid
      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