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