1 /* 2 * Copyright (C) 2017 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.callpending; 18 19 import android.content.BroadcastReceiver; 20 import android.content.Context; 21 import android.content.Intent; 22 import android.content.IntentFilter; 23 import android.graphics.drawable.Drawable; 24 import android.net.Uri; 25 import android.os.Bundle; 26 import android.support.v4.app.FragmentActivity; 27 import android.telecom.CallAudioState; 28 import android.telecom.TelecomManager; 29 import com.android.dialer.common.LogUtil; 30 import com.android.dialer.enrichedcall.EnrichedCallComponent; 31 import com.android.dialer.enrichedcall.Session; 32 import com.android.dialer.multimedia.MultimediaData; 33 import com.android.incallui.audiomode.AudioModeProvider; 34 import com.android.incallui.call.state.DialerCallState; 35 import com.android.incallui.incall.bindings.InCallBindings; 36 import com.android.incallui.incall.protocol.ContactPhotoType; 37 import com.android.incallui.incall.protocol.InCallButtonIds; 38 import com.android.incallui.incall.protocol.InCallButtonUi; 39 import com.android.incallui.incall.protocol.InCallButtonUiDelegate; 40 import com.android.incallui.incall.protocol.InCallButtonUiDelegateFactory; 41 import com.android.incallui.incall.protocol.InCallScreen; 42 import com.android.incallui.incall.protocol.InCallScreenDelegate; 43 import com.android.incallui.incall.protocol.InCallScreenDelegateFactory; 44 import com.android.incallui.incall.protocol.PrimaryCallState; 45 import com.android.incallui.incall.protocol.PrimaryInfo; 46 import java.io.FileNotFoundException; 47 import java.io.InputStream; 48 49 /** 50 * Activity useful for showing the incall ui without an actual call being placed. 51 * 52 * <p>The UI currently displays the following: 53 * 54 * <ul> 55 * <li>Contact info 56 * <li>"Dialing..." call state 57 * <li>Enriched calling data 58 * </ul> 59 * 60 * If the user presses the back or disconnect buttons, {@link #finish()} is called. 61 */ 62 public class CallPendingActivity extends FragmentActivity 63 implements InCallButtonUiDelegateFactory, InCallScreenDelegateFactory { 64 65 private static final String TAG_IN_CALL_SCREEN = "tag_in_call_screen"; 66 private static final String ACTION_FINISH_BROADCAST = 67 "dialer.intent.action.CALL_PENDING_ACTIVITY_FINISH"; 68 69 private static final String EXTRA_SESSION_ID = "extra_session_id"; 70 private static final String EXTRA_NUMBER = "extra_number"; 71 private static final String EXTRA_NAME = "extra_name"; 72 private static final String EXTRA_LABEL = "extra_label"; 73 private static final String EXTRA_LOOKUP_KEY = "extra_lookup_key"; 74 private static final String EXTRA_CALL_PENDING_LABEL = "extra_call_pending_label"; 75 private static final String EXTRA_PHOTO_URI = "extra_photo_uri"; 76 77 private final BroadcastReceiver finishReceiver = 78 new BroadcastReceiver() { 79 @Override 80 public void onReceive(Context arg0, Intent intent) { 81 LogUtil.i("CallPendingActivity.onReceive", "finish broadcast received"); 82 String action = intent.getAction(); 83 if (action.equals(ACTION_FINISH_BROADCAST)) { 84 finish(); 85 } 86 } 87 }; 88 89 private InCallButtonUiDelegate inCallButtonUiDelegate; 90 private InCallScreenDelegate inCallScreenDelegate; 91 getIntent( Context context, String name, String number, String label, String lookupKey, String callPendingLabel, Uri photoUri, long sessionId)92 public static Intent getIntent( 93 Context context, 94 String name, 95 String number, 96 String label, 97 String lookupKey, 98 String callPendingLabel, 99 Uri photoUri, 100 long sessionId) { 101 Intent intent = new Intent(context, CallPendingActivity.class); 102 intent.putExtra(EXTRA_NAME, name); 103 intent.putExtra(EXTRA_NUMBER, number); 104 intent.putExtra(EXTRA_LABEL, label); 105 intent.putExtra(EXTRA_LOOKUP_KEY, lookupKey); 106 intent.putExtra(EXTRA_CALL_PENDING_LABEL, callPendingLabel); 107 intent.putExtra(EXTRA_PHOTO_URI, photoUri); 108 intent.putExtra(EXTRA_SESSION_ID, sessionId); 109 return intent; 110 } 111 getFinishBroadcast()112 public static Intent getFinishBroadcast() { 113 return new Intent(ACTION_FINISH_BROADCAST); 114 } 115 116 @Override onCreate(Bundle savedInstanceState)117 protected void onCreate(Bundle savedInstanceState) { 118 super.onCreate(savedInstanceState); 119 setContentView(R.layout.pending_incall_screen); 120 registerReceiver(finishReceiver, new IntentFilter(ACTION_FINISH_BROADCAST)); 121 } 122 123 @Override onStart()124 protected void onStart() { 125 super.onStart(); 126 InCallScreen inCallScreen = InCallBindings.createInCallScreen(); 127 getSupportFragmentManager() 128 .beginTransaction() 129 .add(R.id.main, inCallScreen.getInCallScreenFragment(), TAG_IN_CALL_SCREEN) 130 .commit(); 131 } 132 133 @Override onResume()134 protected void onResume() { 135 super.onResume(); 136 setupInCallScreen(); 137 } 138 139 @Override onDestroy()140 protected void onDestroy() { 141 super.onDestroy(); 142 unregisterReceiver(finishReceiver); 143 } 144 setupInCallScreen()145 private void setupInCallScreen() { 146 InCallScreen inCallScreen = 147 (InCallScreen) getSupportFragmentManager().findFragmentByTag(TAG_IN_CALL_SCREEN); 148 inCallScreen.setPrimary(createPrimaryInfo()); 149 inCallScreen.setCallState( 150 PrimaryCallState.builder() 151 .setState(DialerCallState.CALL_PENDING) 152 .setCustomLabel(getCallPendingLabel()) 153 .build()); 154 inCallScreen.setEndCallButtonEnabled(true, true); 155 } 156 createPrimaryInfo()157 private PrimaryInfo createPrimaryInfo() { 158 Session session = 159 EnrichedCallComponent.get(this).getEnrichedCallManager().getSession(getSessionId()); 160 MultimediaData multimediaData; 161 if (session == null) { 162 LogUtil.i("CallPendingActivity.createPrimaryInfo", "Null session."); 163 multimediaData = null; 164 } else { 165 multimediaData = session.getMultimediaData(); 166 } 167 168 Drawable photo = null; 169 Uri photoUri = getPhotoUri(); 170 try { 171 // TODO(calderwoodra) move to background thread 172 InputStream is = getContentResolver().openInputStream(photoUri); 173 photo = Drawable.createFromStream(is, photoUri.toString()); 174 } catch (FileNotFoundException e) { 175 LogUtil.e("CallPendingActivity.createPrimaryInfo", "Contact photo not found", e); 176 } 177 178 String name = getName(); 179 String number = getNumber(); 180 181 // DialerCall with caller that is a work contact. 182 return PrimaryInfo.builder() 183 .setNumber(number) 184 .setName(name) 185 .setNameIsNumber(name != null && name.equals(number)) 186 .setLabel(getPhoneLabel()) 187 .setPhoto(photo) 188 .setPhotoUri(photoUri) 189 .setPhotoType(ContactPhotoType.CONTACT) 190 .setIsSipCall(false) 191 .setIsContactPhotoShown(true) 192 .setIsWorkCall(false) 193 .setIsSpam(false) 194 .setIsLocalContact(true) 195 .setAnsweringDisconnectsOngoingCall(false) 196 .setShouldShowLocation(false) 197 .setContactInfoLookupKey(getLookupKey()) 198 .setMultimediaData(multimediaData) 199 .setShowInCallButtonGrid(false) 200 .setNumberPresentation(TelecomManager.PRESENTATION_ALLOWED) 201 .build(); 202 } 203 204 @Override newInCallButtonUiDelegate()205 public InCallButtonUiDelegate newInCallButtonUiDelegate() { 206 if (inCallButtonUiDelegate != null) { 207 return inCallButtonUiDelegate; 208 } 209 return inCallButtonUiDelegate = 210 new InCallButtonUiDelegate() { 211 212 @Override 213 public void onInCallButtonUiReady(InCallButtonUi inCallButtonUi) { 214 inCallButtonUi.showButton(InCallButtonIds.BUTTON_DIALPAD, true); 215 inCallButtonUi.showButton(InCallButtonIds.BUTTON_MUTE, true); 216 inCallButtonUi.showButton(InCallButtonIds.BUTTON_AUDIO, true); 217 inCallButtonUi.showButton(InCallButtonIds.BUTTON_ADD_CALL, true); 218 219 inCallButtonUi.enableButton(InCallButtonIds.BUTTON_DIALPAD, false); 220 inCallButtonUi.enableButton(InCallButtonIds.BUTTON_MUTE, false); 221 inCallButtonUi.enableButton(InCallButtonIds.BUTTON_AUDIO, false); 222 inCallButtonUi.enableButton(InCallButtonIds.BUTTON_ADD_CALL, false); 223 } 224 225 @Override 226 public void onInCallButtonUiUnready() {} 227 228 @Override 229 public void onSaveInstanceState(Bundle outState) {} 230 231 @Override 232 public void onRestoreInstanceState(Bundle savedInstanceState) {} 233 234 @Override 235 public void refreshMuteState() {} 236 237 @Override 238 public void addCallClicked() {} 239 240 @Override 241 public void muteClicked(boolean checked, boolean clickedByUser) {} 242 243 @Override 244 public void mergeClicked() {} 245 246 @Override 247 public void holdClicked(boolean checked) {} 248 249 @Override 250 public void swapClicked() {} 251 252 @Override 253 public void showDialpadClicked(boolean checked) {} 254 255 @Override 256 public void changeToVideoClicked() {} 257 258 @Override 259 public void changeToRttClicked() {} 260 261 @Override 262 public void switchCameraClicked(boolean useFrontFacingCamera) {} 263 264 @Override 265 public void toggleCameraClicked() {} 266 267 @Override 268 public void pauseVideoClicked(boolean pause) {} 269 270 @Override 271 public void toggleSpeakerphone() {} 272 273 @Override 274 public CallAudioState getCurrentAudioState() { 275 return AudioModeProvider.getInstance().getAudioState(); 276 } 277 278 @Override 279 public void setAudioRoute(int route) {} 280 281 @Override 282 public void onEndCallClicked() {} 283 284 @Override 285 public void showAudioRouteSelector() {} 286 287 @Override 288 public void swapSimClicked() {} 289 290 @Override 291 public Context getContext() { 292 return CallPendingActivity.this; 293 } 294 }; 295 } 296 297 @Override 298 public InCallScreenDelegate newInCallScreenDelegate() { 299 if (inCallScreenDelegate != null) { 300 return inCallScreenDelegate; 301 } 302 return inCallScreenDelegate = 303 new InCallScreenDelegate() { 304 305 @Override 306 public void onInCallScreenDelegateInit(InCallScreen inCallScreen) {} 307 308 @Override 309 public void onInCallScreenReady() {} 310 311 @Override 312 public void onInCallScreenUnready() {} 313 314 @Override 315 public void onEndCallClicked() { 316 finish(); 317 } 318 319 @Override 320 public void onSecondaryInfoClicked() {} 321 322 @Override 323 public void onCallStateButtonClicked() {} 324 325 @Override 326 public void onManageConferenceClicked() {} 327 328 @Override 329 public void onShrinkAnimationComplete() {} 330 331 @Override 332 public void onInCallScreenResumed() {} 333 334 @Override 335 public void onInCallScreenPaused() {} 336 }; 337 } 338 339 private long getSessionId() { 340 return getIntent().getLongExtra(EXTRA_SESSION_ID, -1); 341 } 342 343 private String getNumber() { 344 return getIntent().getStringExtra(EXTRA_NUMBER); 345 } 346 347 private String getName() { 348 return getIntent().getStringExtra(EXTRA_NAME); 349 } 350 351 private String getPhoneLabel() { 352 return getIntent().getStringExtra(EXTRA_LABEL); 353 } 354 355 private String getLookupKey() { 356 return getIntent().getStringExtra(EXTRA_LOOKUP_KEY); 357 } 358 359 private String getCallPendingLabel() { 360 return getIntent().getStringExtra(EXTRA_CALL_PENDING_LABEL); 361 } 362 363 private Uri getPhotoUri() { 364 return getIntent().getParcelableExtra(EXTRA_PHOTO_URI); 365 } 366 } 367