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