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.DialerCall.State; 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(State.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 try { 170 // TODO(calderwoodra) move to background thread 171 Uri photoUri = getPhotoUri(); 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 .setPhotoType(ContactPhotoType.CONTACT) 189 .setIsSipCall(false) 190 .setIsContactPhotoShown(true) 191 .setIsWorkCall(false) 192 .setIsSpam(false) 193 .setIsLocalContact(true) 194 .setAnsweringDisconnectsOngoingCall(false) 195 .setShouldShowLocation(false) 196 .setContactInfoLookupKey(getLookupKey()) 197 .setMultimediaData(multimediaData) 198 .setShowInCallButtonGrid(false) 199 .setNumberPresentation(TelecomManager.PRESENTATION_ALLOWED) 200 .build(); 201 } 202 203 @Override newInCallButtonUiDelegate()204 public InCallButtonUiDelegate newInCallButtonUiDelegate() { 205 if (inCallButtonUiDelegate != null) { 206 return inCallButtonUiDelegate; 207 } 208 return inCallButtonUiDelegate = 209 new InCallButtonUiDelegate() { 210 211 @Override 212 public void onInCallButtonUiReady(InCallButtonUi inCallButtonUi) { 213 inCallButtonUi.showButton(InCallButtonIds.BUTTON_DIALPAD, true); 214 inCallButtonUi.showButton(InCallButtonIds.BUTTON_MUTE, true); 215 inCallButtonUi.showButton(InCallButtonIds.BUTTON_AUDIO, true); 216 inCallButtonUi.showButton(InCallButtonIds.BUTTON_ADD_CALL, true); 217 218 inCallButtonUi.enableButton(InCallButtonIds.BUTTON_DIALPAD, false); 219 inCallButtonUi.enableButton(InCallButtonIds.BUTTON_MUTE, false); 220 inCallButtonUi.enableButton(InCallButtonIds.BUTTON_AUDIO, false); 221 inCallButtonUi.enableButton(InCallButtonIds.BUTTON_ADD_CALL, false); 222 } 223 224 @Override 225 public void onInCallButtonUiUnready() {} 226 227 @Override 228 public void onSaveInstanceState(Bundle outState) {} 229 230 @Override 231 public void onRestoreInstanceState(Bundle savedInstanceState) {} 232 233 @Override 234 public void refreshMuteState() {} 235 236 @Override 237 public void addCallClicked() {} 238 239 @Override 240 public void muteClicked(boolean checked, boolean clickedByUser) {} 241 242 @Override 243 public void mergeClicked() {} 244 245 @Override 246 public void holdClicked(boolean checked) {} 247 248 @Override 249 public void swapClicked() {} 250 251 @Override 252 public void showDialpadClicked(boolean checked) {} 253 254 @Override 255 public void changeToVideoClicked() {} 256 257 @Override 258 public void switchCameraClicked(boolean useFrontFacingCamera) {} 259 260 @Override 261 public void toggleCameraClicked() {} 262 263 @Override 264 public void pauseVideoClicked(boolean pause) {} 265 266 @Override 267 public void toggleSpeakerphone() {} 268 269 @Override 270 public CallAudioState getCurrentAudioState() { 271 return AudioModeProvider.getInstance().getAudioState(); 272 } 273 274 @Override 275 public void setAudioRoute(int route) {} 276 277 @Override 278 public void onEndCallClicked() {} 279 280 @Override 281 public void showAudioRouteSelector() {} 282 283 @Override 284 public void swapSimClicked() {} 285 286 @Override 287 public Context getContext() { 288 return CallPendingActivity.this; 289 } 290 }; 291 } 292 293 @Override 294 public InCallScreenDelegate newInCallScreenDelegate() { 295 if (inCallScreenDelegate != null) { 296 return inCallScreenDelegate; 297 } 298 return inCallScreenDelegate = 299 new InCallScreenDelegate() { 300 301 @Override 302 public void onInCallScreenDelegateInit(InCallScreen inCallScreen) {} 303 304 @Override 305 public void onInCallScreenReady() {} 306 307 @Override 308 public void onInCallScreenUnready() {} 309 310 @Override 311 public void onEndCallClicked() { 312 finish(); 313 } 314 315 @Override 316 public void onSecondaryInfoClicked() {} 317 318 @Override 319 public void onCallStateButtonClicked() {} 320 321 @Override 322 public void onManageConferenceClicked() {} 323 324 @Override 325 public void onShrinkAnimationComplete() {} 326 327 @Override 328 public void onInCallScreenResumed() {} 329 330 @Override 331 public void onInCallScreenPaused() {} 332 }; 333 } 334 335 private long getSessionId() { 336 return getIntent().getLongExtra(EXTRA_SESSION_ID, -1); 337 } 338 339 private String getNumber() { 340 return getIntent().getStringExtra(EXTRA_NUMBER); 341 } 342 343 private String getName() { 344 return getIntent().getStringExtra(EXTRA_NAME); 345 } 346 347 private String getPhoneLabel() { 348 return getIntent().getStringExtra(EXTRA_LABEL); 349 } 350 351 private String getLookupKey() { 352 return getIntent().getStringExtra(EXTRA_LOOKUP_KEY); 353 } 354 355 private String getCallPendingLabel() { 356 return getIntent().getStringExtra(EXTRA_CALL_PENDING_LABEL); 357 } 358 359 private Uri getPhotoUri() { 360 return getIntent().getParcelableExtra(EXTRA_PHOTO_URI); 361 } 362 } 363