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 addCallClicked() {} 236 237 @Override 238 public void muteClicked(boolean checked, boolean clickedByUser) {} 239 240 @Override 241 public void mergeClicked() {} 242 243 @Override 244 public void holdClicked(boolean checked) {} 245 246 @Override 247 public void swapClicked() {} 248 249 @Override 250 public void showDialpadClicked(boolean checked) {} 251 252 @Override 253 public void changeToVideoClicked() {} 254 255 @Override 256 public void changeToRttClicked() {} 257 258 @Override 259 public void switchCameraClicked(boolean useFrontFacingCamera) {} 260 261 @Override 262 public void toggleCameraClicked() {} 263 264 @Override 265 public void pauseVideoClicked(boolean pause) {} 266 267 @Override 268 public void toggleSpeakerphone() {} 269 270 @Override 271 public CallAudioState getCurrentAudioState() { 272 return AudioModeProvider.getInstance().getAudioState(); 273 } 274 275 @Override 276 public void setAudioRoute(int route) {} 277 278 @Override 279 public void onEndCallClicked() {} 280 281 @Override 282 public void showAudioRouteSelector() {} 283 284 @Override 285 public void swapSimClicked() {} 286 287 @Override 288 public Context getContext() { 289 return CallPendingActivity.this; 290 } 291 }; 292 } 293 294 @Override 295 public InCallScreenDelegate newInCallScreenDelegate() { 296 if (inCallScreenDelegate != null) { 297 return inCallScreenDelegate; 298 } 299 return inCallScreenDelegate = 300 new InCallScreenDelegate() { 301 302 @Override 303 public void onInCallScreenDelegateInit(InCallScreen inCallScreen) {} 304 305 @Override 306 public void onInCallScreenReady() {} 307 308 @Override 309 public void onInCallScreenUnready() {} 310 311 @Override 312 public void onEndCallClicked() { 313 finish(); 314 } 315 316 @Override 317 public void onSecondaryInfoClicked() {} 318 319 @Override 320 public void onCallStateButtonClicked() {} 321 322 @Override 323 public void onManageConferenceClicked() {} 324 325 @Override 326 public void onShrinkAnimationComplete() {} 327 328 @Override 329 public void onInCallScreenResumed() {} 330 331 @Override 332 public void onInCallScreenPaused() {} 333 }; 334 } 335 336 private long getSessionId() { 337 return getIntent().getLongExtra(EXTRA_SESSION_ID, -1); 338 } 339 340 private String getNumber() { 341 return getIntent().getStringExtra(EXTRA_NUMBER); 342 } 343 344 private String getName() { 345 return getIntent().getStringExtra(EXTRA_NAME); 346 } 347 348 private String getPhoneLabel() { 349 return getIntent().getStringExtra(EXTRA_LABEL); 350 } 351 352 private String getLookupKey() { 353 return getIntent().getStringExtra(EXTRA_LOOKUP_KEY); 354 } 355 356 private String getCallPendingLabel() { 357 return getIntent().getStringExtra(EXTRA_CALL_PENDING_LABEL); 358 } 359 360 private Uri getPhotoUri() { 361 return getIntent().getParcelableExtra(EXTRA_PHOTO_URI); 362 } 363 } 364