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.dialer.precall.externalreceiver;
18 
19 import android.app.Activity;
20 import android.content.Context;
21 import android.content.Intent;
22 import android.os.Bundle;
23 import android.support.annotation.Nullable;
24 import android.telecom.PhoneAccountHandle;
25 import android.telecom.TelecomManager;
26 import android.telecom.VideoProfile;
27 import com.android.dialer.callintent.CallInitiationType.Type;
28 import com.android.dialer.callintent.CallIntentBuilder;
29 import com.android.dialer.common.LogUtil;
30 import com.android.dialer.configprovider.ConfigProvider;
31 import com.android.dialer.configprovider.ConfigProviderComponent;
32 import com.android.dialer.logging.DialerImpression;
33 import com.android.dialer.logging.Logger;
34 import com.android.dialer.precall.PreCall;
35 import com.google.common.collect.ImmutableList;
36 
37 /**
38  * Activity that forwards to {@link PreCall#start(Context, CallIntentBuilder)} so the pre-call flow
39  * can be initiated by external apps. This activity is exported but can only be started by apps with
40  * {@link android.Manifest.permission#CALL_PHONE}. Keyguard will be triggered if phone is locked.
41  *
42  * @see CallIntentBuilder
43  */
44 public class LaunchPreCallActivity extends Activity {
45 
46   public static final String ACTION_LAUNCH_PRE_CALL = "com.android.dialer.LAUNCH_PRE_CALL";
47 
48   public static final String EXTRA_PHONE_ACCOUNT_HANDLE = "phone_account_handle";
49 
50   public static final String EXTRA_IS_VIDEO_CALL = "is_video_call";
51 
52   public static final String EXTRA_CALL_SUBJECT = "call_subject";
53 
54   public static final String EXTRA_ALLOW_ASSISTED_DIAL = "allow_assisted_dial";
55 
56   private static final ImmutableList<String> HANDLED_INTENT_EXTRAS =
57       ImmutableList.of(
58           TelecomManager.EXTRA_START_CALL_WITH_VIDEO_STATE,
59           TelecomManager.EXTRA_OUTGOING_CALL_EXTRAS,
60           TelecomManager.EXTRA_PHONE_ACCOUNT_HANDLE,
61           TelecomManager.EXTRA_CALL_SUBJECT,
62           EXTRA_PHONE_ACCOUNT_HANDLE,
63           EXTRA_IS_VIDEO_CALL,
64           EXTRA_CALL_SUBJECT,
65           EXTRA_ALLOW_ASSISTED_DIAL);
66 
67   @Override
onCreate(@ullable Bundle savedInstanceState)68   public void onCreate(@Nullable Bundle savedInstanceState) {
69     super.onCreate(savedInstanceState);
70     Logger.get(this).logImpression(DialerImpression.Type.PRECALL_INITIATED_EXTERNAL);
71 
72     ConfigProvider configProvider =
73         ConfigProviderComponent.get(getApplicationContext()).getConfigProvider();
74     Intent intent = getIntent();
75     CallIntentBuilder builder = new CallIntentBuilder(intent.getData(), Type.EXTERNAL_INITIATION);
76 
77     PhoneAccountHandle phoneAccountHandle = intent.getParcelableExtra(EXTRA_PHONE_ACCOUNT_HANDLE);
78     if (phoneAccountHandle == null) {
79       phoneAccountHandle = intent.getParcelableExtra(TelecomManager.EXTRA_PHONE_ACCOUNT_HANDLE);
80     }
81 
82     builder
83         .setPhoneAccountHandle(phoneAccountHandle)
84         .setIsVideoCall(intent.getBooleanExtra(EXTRA_IS_VIDEO_CALL, false))
85         .setCallSubject(intent.getStringExtra(EXTRA_CALL_SUBJECT))
86         .setAllowAssistedDial(
87             intent.getBooleanExtra(
88                 EXTRA_ALLOW_ASSISTED_DIAL,
89                 configProvider.getBoolean("assisted_dialing_default_precall_state", false)));
90     filterExtras(intent.getExtras(), builder);
91     PreCall.start(this, builder);
92     finish();
93   }
94 
95   /**
96    * Move key-value pairs that {@link CallIntentBuilder} can handle from {@code intentExtras} to
97    * {@code builder}
98    */
filterExtras(@ullable Bundle intentExtras, CallIntentBuilder builder)99   private void filterExtras(@Nullable Bundle intentExtras, CallIntentBuilder builder) {
100     if (intentExtras == null) {
101       return;
102     }
103     Bundle bundle = new Bundle();
104     bundle.putAll(intentExtras);
105 
106     if (intentExtras.containsKey(TelecomManager.EXTRA_START_CALL_WITH_VIDEO_STATE)) {
107       int videoState = intentExtras.getInt(TelecomManager.EXTRA_START_CALL_WITH_VIDEO_STATE);
108       switch (videoState) {
109         case VideoProfile.STATE_BIDIRECTIONAL:
110           builder.setIsVideoCall(true);
111           break;
112         case VideoProfile.STATE_AUDIO_ONLY:
113           builder.setIsVideoCall(false);
114           break;
115         case VideoProfile.STATE_RX_ENABLED:
116         case VideoProfile.STATE_TX_ENABLED:
117           LogUtil.w(
118               "LaunchPreCallActivity.filterExtras",
119               "unsupported video state " + videoState + ", overriding to STATE_BIDIRECTIONAL");
120           builder.setIsVideoCall(true);
121           break;
122         default:
123           LogUtil.w("LaunchPreCallActivity.filterExtras", "unknown video state " + videoState);
124           builder.setIsVideoCall(false);
125       }
126     }
127 
128     if (intentExtras.containsKey(TelecomManager.EXTRA_OUTGOING_CALL_EXTRAS)) {
129       builder
130           .getInCallUiIntentExtras()
131           .putAll(intentExtras.getBundle(TelecomManager.EXTRA_OUTGOING_CALL_EXTRAS));
132     }
133 
134     if (intentExtras.containsKey(TelecomManager.EXTRA_PHONE_ACCOUNT_HANDLE)) {
135       builder.setPhoneAccountHandle(
136           intentExtras.getParcelable(TelecomManager.EXTRA_PHONE_ACCOUNT_HANDLE));
137     }
138 
139     if (intentExtras.containsKey(TelecomManager.EXTRA_CALL_SUBJECT)) {
140       builder.setCallSubject(intentExtras.getString(TelecomManager.EXTRA_CALL_SUBJECT));
141     }
142 
143     for (String handledKey : HANDLED_INTENT_EXTRAS) {
144       bundle.remove(handledKey);
145     }
146     builder.getPlaceCallExtras().putAll(bundle);
147   }
148 }
149