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 17package com.android.incallui.callpending; 18 19import android.content.BroadcastReceiver; 20import android.content.Context; 21import android.content.Intent; 22import android.content.IntentFilter; 23import android.graphics.drawable.Drawable; 24import android.net.Uri; 25import android.os.Bundle; 26import android.support.v4.app.FragmentActivity; 27import android.telecom.CallAudioState; 28import android.telecom.TelecomManager; 29import com.android.dialer.common.LogUtil; 30import com.android.dialer.enrichedcall.EnrichedCallComponent; 31import com.android.dialer.enrichedcall.Session; 32import com.android.dialer.multimedia.MultimediaData; 33import com.android.incallui.audiomode.AudioModeProvider; 34import com.android.incallui.call.DialerCall.State; 35import com.android.incallui.incall.bindings.InCallBindings; 36import com.android.incallui.incall.protocol.ContactPhotoType; 37import com.android.incallui.incall.protocol.InCallButtonIds; 38import com.android.incallui.incall.protocol.InCallButtonUi; 39import com.android.incallui.incall.protocol.InCallButtonUiDelegate; 40import com.android.incallui.incall.protocol.InCallButtonUiDelegateFactory; 41import com.android.incallui.incall.protocol.InCallScreen; 42import com.android.incallui.incall.protocol.InCallScreenDelegate; 43import com.android.incallui.incall.protocol.InCallScreenDelegateFactory; 44import com.android.incallui.incall.protocol.PrimaryCallState; 45import com.android.incallui.incall.protocol.PrimaryInfo; 46import java.io.FileNotFoundException; 47import 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 */ 62public 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 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 112 public static Intent getFinishBroadcast() { 113 return new Intent(ACTION_FINISH_BROADCAST); 114 } 115 116 @Override 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 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 134 protected void onResume() { 135 super.onResume(); 136 setupInCallScreen(); 137 } 138 139 @Override 140 protected void onDestroy() { 141 super.onDestroy(); 142 unregisterReceiver(finishReceiver); 143 } 144 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 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 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