• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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.graphics.drawable.Drawable;
21 import android.support.annotation.Nullable;
22 import android.telephony.PhoneNumberUtils;
23 import android.text.BidiFormatter;
24 import android.text.TextDirectionHeuristics;
25 import android.text.TextUtils;
26 import com.android.dialer.common.Assert;
27 import com.android.incallui.call.DialerCall.State;
28 import com.android.incallui.incall.protocol.PrimaryCallState;
29 import com.android.incallui.incall.protocol.PrimaryInfo;
30 import com.android.incallui.videotech.utils.SessionModificationState;
31 import com.android.incallui.videotech.utils.VideoUtils;
32 
33 /**
34  * Gets the content of the top row. For example:
35  *
36  * <ul>
37  *   <li>Captain Holt ON HOLD
38  *   <li>Calling...
39  *   <li>[Wi-Fi icon] Calling via Starbucks Wi-Fi
40  *   <li>[Wi-Fi icon] Starbucks Wi-Fi
41  *   <li>Call from
42  * </ul>
43  */
44 public class TopRow {
45 
46   /** Content of the top row. */
47   public static class Info {
48 
49     @Nullable public final CharSequence label;
50     @Nullable public final Drawable icon;
51     public final boolean labelIsSingleLine;
52 
Info(@ullable CharSequence label, @Nullable Drawable icon, boolean labelIsSingleLine)53     public Info(@Nullable CharSequence label, @Nullable Drawable icon, boolean labelIsSingleLine) {
54       this.label = label;
55       this.icon = icon;
56       this.labelIsSingleLine = labelIsSingleLine;
57     }
58   }
59 
TopRow()60   private TopRow() {}
61 
getInfo(Context context, PrimaryCallState state, PrimaryInfo primaryInfo)62   public static Info getInfo(Context context, PrimaryCallState state, PrimaryInfo primaryInfo) {
63     CharSequence label = null;
64     Drawable icon = state.connectionIcon;
65     boolean labelIsSingleLine = true;
66 
67     if (state.isWifi && icon == null) {
68       icon = context.getDrawable(R.drawable.quantum_ic_network_wifi_vd_theme_24);
69     }
70 
71     if (state.state == State.INCOMING || state.state == State.CALL_WAITING) {
72       // Call from
73       // [Wi-Fi icon] Video call from
74       // Hey Jake, pick up!
75       if (!TextUtils.isEmpty(state.callSubject)) {
76         label = state.callSubject;
77         labelIsSingleLine = false;
78       } else {
79         label = getLabelForIncoming(context, state);
80         // Show phone number if it's not displayed in name (center row) or location field (bottom
81         // row).
82         if (shouldShowNumber(primaryInfo)) {
83           label = TextUtils.concat(label, " ", spanDisplayNumber(primaryInfo.number));
84         }
85       }
86     } else if (VideoUtils.hasSentVideoUpgradeRequest(state.sessionModificationState)
87         || VideoUtils.hasReceivedVideoUpgradeRequest(state.sessionModificationState)) {
88       label = getLabelForVideoRequest(context, state);
89     } else if (state.state == State.PULLING) {
90       label = context.getString(R.string.incall_transferring);
91     } else if (state.state == State.DIALING || state.state == State.CONNECTING) {
92       // [Wi-Fi icon] Calling via Google Guest
93       // Calling...
94       label = getLabelForDialing(context, state);
95     } else if (state.state == State.ACTIVE && state.isRemotelyHeld) {
96       label = context.getString(R.string.incall_remotely_held);
97     } else if (state.state == State.ACTIVE && shouldShowNumber(primaryInfo)) {
98       label = spanDisplayNumber(primaryInfo.number);
99     } else {
100       // Video calling...
101       // [Wi-Fi icon] Starbucks Wi-Fi
102       label = getConnectionLabel(state);
103     }
104 
105     return new Info(label, icon, labelIsSingleLine);
106   }
107 
spanDisplayNumber(String displayNumber)108   private static CharSequence spanDisplayNumber(String displayNumber) {
109     return PhoneNumberUtils.createTtsSpannable(
110         BidiFormatter.getInstance().unicodeWrap(displayNumber, TextDirectionHeuristics.LTR));
111   }
112 
shouldShowNumber(PrimaryInfo primaryInfo)113   private static boolean shouldShowNumber(PrimaryInfo primaryInfo) {
114     if (primaryInfo.nameIsNumber) {
115       return false;
116     }
117     if (primaryInfo.location == null) {
118       return false;
119     }
120     if (TextUtils.isEmpty(primaryInfo.number)) {
121       return false;
122     }
123     return true;
124   }
125 
getLabelForIncoming(Context context, PrimaryCallState state)126   private static CharSequence getLabelForIncoming(Context context, PrimaryCallState state) {
127     if (state.isVideoCall) {
128       return getLabelForIncomingVideo(context, state.sessionModificationState, state.isWifi);
129     } else if (state.isWifi && !TextUtils.isEmpty(state.connectionLabel)) {
130       return state.connectionLabel;
131     } else if (isAccount(state)) {
132       return context.getString(R.string.contact_grid_incoming_via_template, state.connectionLabel);
133     } else if (state.isWorkCall) {
134       return context.getString(R.string.contact_grid_incoming_work_call);
135     } else {
136       return context.getString(R.string.contact_grid_incoming_voice_call);
137     }
138   }
139 
getLabelForIncomingVideo( Context context, @SessionModificationState int sessionModificationState, boolean isWifi)140   private static CharSequence getLabelForIncomingVideo(
141       Context context, @SessionModificationState int sessionModificationState, boolean isWifi) {
142     if (sessionModificationState == SessionModificationState.RECEIVED_UPGRADE_TO_VIDEO_REQUEST) {
143       if (isWifi) {
144         return context.getString(R.string.contact_grid_incoming_wifi_video_request);
145       } else {
146         return context.getString(R.string.contact_grid_incoming_video_request);
147       }
148     } else {
149       if (isWifi) {
150         return context.getString(R.string.contact_grid_incoming_wifi_video_call);
151       } else {
152         return context.getString(R.string.contact_grid_incoming_video_call);
153       }
154     }
155   }
156 
getLabelForDialing(Context context, PrimaryCallState state)157   private static CharSequence getLabelForDialing(Context context, PrimaryCallState state) {
158     if (!TextUtils.isEmpty(state.connectionLabel) && !state.isWifi) {
159       return context.getString(R.string.incall_calling_via_template, state.connectionLabel);
160     } else {
161       if (state.isVideoCall) {
162         if (state.isWifi) {
163           return context.getString(R.string.incall_wifi_video_call_requesting);
164         } else {
165           return context.getString(R.string.incall_video_call_requesting);
166         }
167       }
168       return context.getString(R.string.incall_connecting);
169     }
170   }
171 
getConnectionLabel(PrimaryCallState state)172   private static CharSequence getConnectionLabel(PrimaryCallState state) {
173     if (!TextUtils.isEmpty(state.connectionLabel)
174         && (isAccount(state) || state.isWifi || state.isConference)) {
175       // We normally don't show a "call state label" at all when active
176       // (but we can use the call state label to display the provider name).
177       return state.connectionLabel;
178     } else {
179       return null;
180     }
181   }
182 
getLabelForVideoRequest(Context context, PrimaryCallState state)183   private static CharSequence getLabelForVideoRequest(Context context, PrimaryCallState state) {
184     switch (state.sessionModificationState) {
185       case SessionModificationState.WAITING_FOR_UPGRADE_TO_VIDEO_RESPONSE:
186         return context.getString(R.string.incall_video_call_requesting);
187       case SessionModificationState.REQUEST_FAILED:
188       case SessionModificationState.UPGRADE_TO_VIDEO_REQUEST_FAILED:
189         return context.getString(R.string.incall_video_call_request_failed);
190       case SessionModificationState.REQUEST_REJECTED:
191         return context.getString(R.string.incall_video_call_request_rejected);
192       case SessionModificationState.UPGRADE_TO_VIDEO_REQUEST_TIMED_OUT:
193         return context.getString(R.string.incall_video_call_request_timed_out);
194       case SessionModificationState.RECEIVED_UPGRADE_TO_VIDEO_REQUEST:
195         return getLabelForIncomingVideo(context, state.sessionModificationState, state.isWifi);
196       case SessionModificationState.NO_REQUEST:
197       default:
198         Assert.fail();
199         return null;
200     }
201   }
202 
isAccount(PrimaryCallState state)203   private static boolean isAccount(PrimaryCallState state) {
204     return !TextUtils.isEmpty(state.connectionLabel) && TextUtils.isEmpty(state.gatewayNumber);
205   }
206 }
207