blob: 2c009411b368f49a906584a0ed10c6f52f867193 [file] [log] [blame]
Santos Cordonf987d1a2014-12-02 03:37:03 -08001/*
2 * Copyright (C) 2014 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.server.telecom;
18
Yorke Leecb0bd8a2015-05-18 11:57:14 -070019import static android.Manifest.permission.CALL_PHONE;
Tyler Gunnb652dad2018-03-27 18:49:49 +000020import static android.Manifest.permission.CALL_PRIVILEGED;
Hall Liuecd74a52016-01-12 15:26:36 -080021import static android.Manifest.permission.DUMP;
Yorke Leecb0bd8a2015-05-18 11:57:14 -070022import static android.Manifest.permission.MODIFY_PHONE_STATE;
23import static android.Manifest.permission.READ_PHONE_STATE;
Amit Mahajan3c296932015-07-14 10:23:15 -070024import static android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE;
Yorke Leecb0bd8a2015-05-18 11:57:14 -070025import static android.Manifest.permission.REGISTER_SIM_SUBSCRIPTION;
Yorke Lee71734c22015-06-02 14:22:56 -070026import static android.Manifest.permission.WRITE_SECURE_SETTINGS;
Yorke Leecb0bd8a2015-05-18 11:57:14 -070027
Tyler Gunna90ba732017-01-26 07:24:08 -080028import android.Manifest;
Yorke Leeb3984302015-06-15 12:06:35 -070029import android.app.ActivityManager;
Santos Cordonf987d1a2014-12-02 03:37:03 -080030import android.app.AppOpsManager;
Santos Cordonf987d1a2014-12-02 03:37:03 -080031import android.content.ComponentName;
32import android.content.Context;
33import android.content.Intent;
34import android.content.pm.ApplicationInfo;
35import android.content.pm.PackageManager;
36import android.content.res.Resources;
37import android.net.Uri;
38import android.os.Binder;
39import android.os.Bundle;
Tony Mak240656f2015-12-04 11:36:22 +000040import android.os.Process;
Santos Cordonf987d1a2014-12-02 03:37:03 -080041import android.os.UserHandle;
Brad Ebingera3eccfe2016-10-05 15:45:22 -070042import android.telecom.Log;
Santos Cordonf987d1a2014-12-02 03:37:03 -080043import android.telecom.PhoneAccount;
44import android.telecom.PhoneAccountHandle;
Hall Liu874c0f82016-04-29 18:13:18 -070045import android.telecom.TelecomAnalytics;
Santos Cordonf987d1a2014-12-02 03:37:03 -080046import android.telecom.TelecomManager;
Tyler Gunn42ef8082015-11-24 15:34:34 -080047import android.telecom.VideoProfile;
Santos Cordonf987d1a2014-12-02 03:37:03 -080048import android.telephony.SubscriptionManager;
49import android.telephony.TelephonyManager;
Tyler Gunn0edfc662017-04-14 13:46:21 -070050import android.text.TextUtils;
Brad Ebinger62da8e12016-01-28 19:16:08 -080051import android.util.EventLog;
Santos Cordonf987d1a2014-12-02 03:37:03 -080052
Santos Cordonf987d1a2014-12-02 03:37:03 -080053import com.android.internal.telecom.ITelecomService;
54import com.android.internal.util.IndentingPrintWriter;
Hall Liuecda5542015-12-04 11:31:31 -080055import com.android.server.telecom.components.UserCallIntentProcessorFactory;
Mohamedc9261852016-02-05 14:10:17 -080056import com.android.server.telecom.settings.BlockedNumbersActivity;
Santos Cordonf987d1a2014-12-02 03:37:03 -080057
58import java.io.FileDescriptor;
59import java.io.PrintWriter;
Svet Ganov09611182015-04-16 12:29:01 -070060import java.util.Collections;
Santos Cordonf987d1a2014-12-02 03:37:03 -080061import java.util.List;
62
Eugene Suslaccba7202017-02-10 10:56:53 -080063// TODO: Needed for move to system service: import com.android.internal.R;
64
Santos Cordonf987d1a2014-12-02 03:37:03 -080065/**
66 * Implementation of the ITelecom interface.
67 */
Ihab Awad78a5e6b2015-02-06 10:13:05 -080068public class TelecomServiceImpl {
Hall Liu0a6dd302015-12-16 15:06:49 -080069
70 public interface SubscriptionManagerAdapter {
71 int getDefaultVoiceSubId();
72 }
73
74 static class SubscriptionManagerAdapterImpl implements SubscriptionManagerAdapter {
75 @Override
76 public int getDefaultVoiceSubId() {
Shishir Agrawalce688742016-01-25 15:02:21 -080077 return SubscriptionManager.getDefaultVoiceSubscriptionId();
Hall Liu0a6dd302015-12-16 15:06:49 -080078 }
79 }
80
Tyler Gunn897e8512017-05-18 15:46:51 -070081 private static final String TIME_LINE_ARG = "timeline";
Tyler Gunn42ef8082015-11-24 15:34:34 -080082 private static final int DEFAULT_VIDEO_STATE = -1;
Santos Cordon73853962015-02-27 15:13:35 -080083
Ihab Awad8d5d9dd2015-03-12 11:11:06 -070084 private final ITelecomService.Stub mBinderImpl = new ITelecomService.Stub() {
Santos Cordonf987d1a2014-12-02 03:37:03 -080085 @Override
Svet Ganov09611182015-04-16 12:29:01 -070086 public PhoneAccountHandle getDefaultOutgoingPhoneAccount(String uriScheme,
87 String callingPackage) {
Brad Ebinger11623a32015-11-25 13:52:02 -080088 try {
89 Log.startSession("TSI.gDOPA");
90 synchronized (mLock) {
91 if (!canReadPhoneState(callingPackage, "getDefaultOutgoingPhoneAccount")) {
92 return null;
93 }
Svet Ganov09611182015-04-16 12:29:01 -070094
Brad Ebinger11623a32015-11-25 13:52:02 -080095 final UserHandle callingUserHandle = Binder.getCallingUserHandle();
96 long token = Binder.clearCallingIdentity();
97 try {
98 return mPhoneAccountRegistrar
99 .getOutgoingPhoneAccountForScheme(uriScheme, callingUserHandle);
100 } catch (Exception e) {
101 Log.e(this, e, "getDefaultOutgoingPhoneAccount");
102 throw e;
103 } finally {
104 Binder.restoreCallingIdentity(token);
105 }
Santos Cordonf987d1a2014-12-02 03:37:03 -0800106 }
Brad Ebinger11623a32015-11-25 13:52:02 -0800107 } finally {
108 Log.endSession();
Santos Cordonf987d1a2014-12-02 03:37:03 -0800109 }
110 }
111
112 @Override
113 public PhoneAccountHandle getUserSelectedOutgoingPhoneAccount() {
Ihab Awad8d5d9dd2015-03-12 11:11:06 -0700114 synchronized (mLock) {
115 try {
Brad Ebinger11623a32015-11-25 13:52:02 -0800116 Log.startSession("TSI.gUSOPA");
Tony Mak240656f2015-12-04 11:36:22 +0000117 final UserHandle callingUserHandle = Binder.getCallingUserHandle();
118 return mPhoneAccountRegistrar.getUserSelectedOutgoingPhoneAccount(
119 callingUserHandle);
Ihab Awad8d5d9dd2015-03-12 11:11:06 -0700120 } catch (Exception e) {
121 Log.e(this, e, "getUserSelectedOutgoingPhoneAccount");
122 throw e;
Brad Ebinger11623a32015-11-25 13:52:02 -0800123 } finally {
124 Log.endSession();
Santos Cordonf987d1a2014-12-02 03:37:03 -0800125 }
Santos Cordonf987d1a2014-12-02 03:37:03 -0800126 }
127 }
128
129 @Override
130 public void setUserSelectedOutgoingPhoneAccount(PhoneAccountHandle accountHandle) {
Brad Ebinger11623a32015-11-25 13:52:02 -0800131 try {
132 Log.startSession("TSI.sUSOPA");
133 synchronized (mLock) {
134 enforceModifyPermission();
135 UserHandle callingUserHandle = Binder.getCallingUserHandle();
136 long token = Binder.clearCallingIdentity();
137 try {
138 mPhoneAccountRegistrar.setUserSelectedOutgoingPhoneAccount(
139 accountHandle, callingUserHandle);
140 } catch (Exception e) {
141 Log.e(this, e, "setUserSelectedOutgoingPhoneAccount");
142 throw e;
143 } finally {
144 Binder.restoreCallingIdentity(token);
145 }
Ihab Awad8d5d9dd2015-03-12 11:11:06 -0700146 }
Brad Ebinger11623a32015-11-25 13:52:02 -0800147 } finally {
148 Log.endSession();
Santos Cordonf987d1a2014-12-02 03:37:03 -0800149 }
150 }
151
152 @Override
Santos Cordonea5cb932015-05-07 16:28:38 -0700153 public List<PhoneAccountHandle> getCallCapablePhoneAccounts(
154 boolean includeDisabledAccounts, String callingPackage) {
Brad Ebinger11623a32015-11-25 13:52:02 -0800155 try {
156 Log.startSession("TSI.gCCPA");
157 if (!canReadPhoneState(callingPackage, "getDefaultOutgoingPhoneAccount")) {
158 return Collections.emptyList();
Ihab Awad8d5d9dd2015-03-12 11:11:06 -0700159 }
Brad Ebinger11623a32015-11-25 13:52:02 -0800160 synchronized (mLock) {
161 final UserHandle callingUserHandle = Binder.getCallingUserHandle();
162 long token = Binder.clearCallingIdentity();
163 try {
164 return mPhoneAccountRegistrar.getCallCapablePhoneAccounts(null,
165 includeDisabledAccounts, callingUserHandle);
166 } catch (Exception e) {
167 Log.e(this, e, "getCallCapablePhoneAccounts");
168 throw e;
169 } finally {
170 Binder.restoreCallingIdentity(token);
171 }
172 }
173 } finally {
174 Log.endSession();
Santos Cordonf987d1a2014-12-02 03:37:03 -0800175 }
176 }
177
178 @Override
Tyler Gunnebfc9162017-04-07 15:00:49 -0700179 public List<PhoneAccountHandle> getSelfManagedPhoneAccounts(String callingPackage) {
180 try {
181 Log.startSession("TSI.gSMPA");
182 if (!canReadPhoneState(callingPackage, "Requires READ_PHONE_STATE permission.")) {
183 throw new SecurityException("Requires READ_PHONE_STATE permission.");
184 }
185 synchronized (mLock) {
186 final UserHandle callingUserHandle = Binder.getCallingUserHandle();
187 long token = Binder.clearCallingIdentity();
188 try {
189 return mPhoneAccountRegistrar.getSelfManagedPhoneAccounts(
190 callingUserHandle);
191 } catch (Exception e) {
192 Log.e(this, e, "getSelfManagedPhoneAccounts");
193 throw e;
194 } finally {
195 Binder.restoreCallingIdentity(token);
196 }
197 }
198 } finally {
199 Log.endSession();
200 }
201 }
202
203 @Override
Svet Ganov09611182015-04-16 12:29:01 -0700204 public List<PhoneAccountHandle> getPhoneAccountsSupportingScheme(String uriScheme,
205 String callingPackage) {
Brad Ebinger11623a32015-11-25 13:52:02 -0800206 try {
207 Log.startSession("TSI.gPASS");
Tyler Gunn322480c2017-07-17 15:34:02 -0700208 try {
209 enforceModifyPermission(
210 "getPhoneAccountsSupportingScheme requires MODIFY_PHONE_STATE");
211 } catch (SecurityException e) {
212 EventLog.writeEvent(0x534e4554, "62347125", Binder.getCallingUid(),
213 "getPhoneAccountsSupportingScheme: " + callingPackage);
214 return Collections.emptyList();
215 }
216
Brad Ebinger11623a32015-11-25 13:52:02 -0800217 synchronized (mLock) {
Brad Ebinger11623a32015-11-25 13:52:02 -0800218 final UserHandle callingUserHandle = Binder.getCallingUserHandle();
219 long token = Binder.clearCallingIdentity();
220 try {
221 return mPhoneAccountRegistrar.getCallCapablePhoneAccounts(uriScheme, false,
222 callingUserHandle);
223 } catch (Exception e) {
224 Log.e(this, e, "getPhoneAccountsSupportingScheme %s", uriScheme);
225 throw e;
226 } finally {
227 Binder.restoreCallingIdentity(token);
228 }
Svet Ganov09611182015-04-16 12:29:01 -0700229 }
Brad Ebinger11623a32015-11-25 13:52:02 -0800230 } finally {
231 Log.endSession();
Santos Cordonf987d1a2014-12-02 03:37:03 -0800232 }
233 }
234
235 @Override
236 public List<PhoneAccountHandle> getPhoneAccountsForPackage(String packageName) {
Ihab Awad8d5d9dd2015-03-12 11:11:06 -0700237 synchronized (mLock) {
Tony Mak240656f2015-12-04 11:36:22 +0000238 final UserHandle callingUserHandle = Binder.getCallingUserHandle();
239 long token = Binder.clearCallingIdentity();
Ihab Awad8d5d9dd2015-03-12 11:11:06 -0700240 try {
Brad Ebinger11623a32015-11-25 13:52:02 -0800241 Log.startSession("TSI.gPAFP");
Tony Mak240656f2015-12-04 11:36:22 +0000242 return mPhoneAccountRegistrar.getPhoneAccountsForPackage(packageName,
243 callingUserHandle);
Ihab Awad8d5d9dd2015-03-12 11:11:06 -0700244 } catch (Exception e) {
245 Log.e(this, e, "getPhoneAccountsForPackage %s", packageName);
246 throw e;
Tony Mak240656f2015-12-04 11:36:22 +0000247 } finally {
248 Binder.restoreCallingIdentity(token);
Brad Ebinger11623a32015-11-25 13:52:02 -0800249 Log.endSession();
Ihab Awad8d5d9dd2015-03-12 11:11:06 -0700250 }
Santos Cordonf987d1a2014-12-02 03:37:03 -0800251 }
252 }
253
254 @Override
255 public PhoneAccount getPhoneAccount(PhoneAccountHandle accountHandle) {
Ihab Awad8d5d9dd2015-03-12 11:11:06 -0700256 synchronized (mLock) {
Tony Mak240656f2015-12-04 11:36:22 +0000257 final UserHandle callingUserHandle = Binder.getCallingUserHandle();
258 long token = Binder.clearCallingIdentity();
Ihab Awad8d5d9dd2015-03-12 11:11:06 -0700259 try {
Brad Ebinger11623a32015-11-25 13:52:02 -0800260 Log.startSession("TSI.gPA");
Tony Mak240656f2015-12-04 11:36:22 +0000261 // In ideal case, we should not resolve the handle across profiles. But given
262 // the fact that profile's call is handled by its parent user's in-call UI,
263 // parent user's in call UI need to be able to get phone account from the
264 // profile's phone account handle.
265 return mPhoneAccountRegistrar
266 .getPhoneAccount(accountHandle, callingUserHandle,
267 /* acrossProfiles */ true);
Ihab Awad8d5d9dd2015-03-12 11:11:06 -0700268 } catch (Exception e) {
269 Log.e(this, e, "getPhoneAccount %s", accountHandle);
270 throw e;
Tony Mak240656f2015-12-04 11:36:22 +0000271 } finally {
272 Binder.restoreCallingIdentity(token);
Brad Ebinger11623a32015-11-25 13:52:02 -0800273 Log.endSession();
Santos Cordonf987d1a2014-12-02 03:37:03 -0800274 }
Santos Cordonf987d1a2014-12-02 03:37:03 -0800275 }
276 }
277
278 @Override
279 public int getAllPhoneAccountsCount() {
Tyler Gunn322480c2017-07-17 15:34:02 -0700280 try {
281 Log.startSession("TSI.gAPAC");
Ihab Awad8d5d9dd2015-03-12 11:11:06 -0700282 try {
Tyler Gunn322480c2017-07-17 15:34:02 -0700283 enforceModifyPermission(
284 "getAllPhoneAccountsCount requires MODIFY_PHONE_STATE permission.");
285 } catch (SecurityException e) {
286 EventLog.writeEvent(0x534e4554, "62347125", Binder.getCallingUid(),
287 "getAllPhoneAccountsCount");
Ihab Awad8d5d9dd2015-03-12 11:11:06 -0700288 throw e;
289 }
Tyler Gunn322480c2017-07-17 15:34:02 -0700290
291 synchronized (mLock) {
292 try {
293 // This list is pre-filtered for the calling user.
294 return getAllPhoneAccounts().size();
295 } catch (Exception e) {
296 Log.e(this, e, "getAllPhoneAccountsCount");
297 throw e;
298
299 }
300 }
301 } finally {
302 Log.endSession();
Santos Cordonf987d1a2014-12-02 03:37:03 -0800303 }
304 }
305
306 @Override
307 public List<PhoneAccount> getAllPhoneAccounts() {
Ihab Awad8d5d9dd2015-03-12 11:11:06 -0700308 synchronized (mLock) {
309 try {
Brad Ebinger11623a32015-11-25 13:52:02 -0800310 Log.startSession("TSI.gAPA");
Tyler Gunn322480c2017-07-17 15:34:02 -0700311 try {
312 enforceModifyPermission(
313 "getAllPhoneAccounts requires MODIFY_PHONE_STATE permission.");
314 } catch (SecurityException e) {
315 EventLog.writeEvent(0x534e4554, "62347125", Binder.getCallingUid(),
316 "getAllPhoneAccounts");
317 throw e;
318 }
319
320 final UserHandle callingUserHandle = Binder.getCallingUserHandle();
321 long token = Binder.clearCallingIdentity();
322 try {
323 return mPhoneAccountRegistrar.getAllPhoneAccounts(callingUserHandle);
324 } catch (Exception e) {
325 Log.e(this, e, "getAllPhoneAccounts");
326 throw e;
327 } finally {
328 Binder.restoreCallingIdentity(token);
329 }
Tony Mak240656f2015-12-04 11:36:22 +0000330 } finally {
Brad Ebinger11623a32015-11-25 13:52:02 -0800331 Log.endSession();
Santos Cordonf987d1a2014-12-02 03:37:03 -0800332 }
Santos Cordonf987d1a2014-12-02 03:37:03 -0800333 }
334 }
335
336 @Override
337 public List<PhoneAccountHandle> getAllPhoneAccountHandles() {
Tyler Gunn322480c2017-07-17 15:34:02 -0700338 try {
339 Log.startSession("TSI.gAPAH");
Ihab Awad8d5d9dd2015-03-12 11:11:06 -0700340 try {
Tyler Gunn322480c2017-07-17 15:34:02 -0700341 enforceModifyPermission(
342 "getAllPhoneAccountHandles requires MODIFY_PHONE_STATE permission.");
343 } catch (SecurityException e) {
344 EventLog.writeEvent(0x534e4554, "62347125", Binder.getCallingUid(),
345 "getAllPhoneAccountHandles");
Ihab Awad8d5d9dd2015-03-12 11:11:06 -0700346 throw e;
347 }
Tyler Gunn322480c2017-07-17 15:34:02 -0700348
349 synchronized (mLock) {
350 final UserHandle callingUserHandle = Binder.getCallingUserHandle();
351 long token = Binder.clearCallingIdentity();
352 try {
353 return mPhoneAccountRegistrar.getAllPhoneAccountHandles(callingUserHandle);
354 } catch (Exception e) {
355 Log.e(this, e, "getAllPhoneAccounts");
356 throw e;
357 } finally {
358 Binder.restoreCallingIdentity(token);
359 }
360 }
361 } finally {
362 Log.endSession();
Santos Cordonf987d1a2014-12-02 03:37:03 -0800363 }
364 }
365
366 @Override
367 public PhoneAccountHandle getSimCallManager() {
Sailesh Nepalfc43ea82015-07-28 19:30:28 -0700368 try {
Brad Ebinger11623a32015-11-25 13:52:02 -0800369 Log.startSession("TSI.gSCM");
370 long token = Binder.clearCallingIdentity();
371 int user;
372 try {
373 user = ActivityManager.getCurrentUser();
374 return getSimCallManagerForUser(user);
375 } finally {
376 Binder.restoreCallingIdentity(token);
377 }
Sailesh Nepalfc43ea82015-07-28 19:30:28 -0700378 } finally {
Brad Ebinger11623a32015-11-25 13:52:02 -0800379 Log.endSession();
Sailesh Nepalfc43ea82015-07-28 19:30:28 -0700380 }
Sailesh Nepalfc43ea82015-07-28 19:30:28 -0700381 }
382
383 @Override
384 public PhoneAccountHandle getSimCallManagerForUser(int user) {
Ihab Awad8d5d9dd2015-03-12 11:11:06 -0700385 synchronized (mLock) {
386 try {
Brad Ebinger11623a32015-11-25 13:52:02 -0800387 Log.startSession("TSI.gSCMFU");
Tony Mak240656f2015-12-04 11:36:22 +0000388 final int callingUid = Binder.getCallingUid();
Santos Cordon59c21a72015-06-11 10:11:21 -0700389 long token = Binder.clearCallingIdentity();
390 try {
Tony Mak240656f2015-12-04 11:36:22 +0000391 if (user != ActivityManager.getCurrentUser()) {
392 enforceCrossUserPermission(callingUid);
393 }
394 return mPhoneAccountRegistrar.getSimCallManager(UserHandle.of(user));
Santos Cordon59c21a72015-06-11 10:11:21 -0700395 } finally {
Santos Cordon59c21a72015-06-11 10:11:21 -0700396 Binder.restoreCallingIdentity(token);
397 }
Ihab Awad8d5d9dd2015-03-12 11:11:06 -0700398 } catch (Exception e) {
399 Log.e(this, e, "getSimCallManager");
400 throw e;
Brad Ebinger11623a32015-11-25 13:52:02 -0800401 } finally {
402 Log.endSession();
Santos Cordonf987d1a2014-12-02 03:37:03 -0800403 }
Santos Cordonf987d1a2014-12-02 03:37:03 -0800404 }
405 }
406
407 @Override
Santos Cordonf987d1a2014-12-02 03:37:03 -0800408 public void registerPhoneAccount(PhoneAccount account) {
Brad Ebinger11623a32015-11-25 13:52:02 -0800409 try {
410 Log.startSession("TSI.rPA");
411 synchronized (mLock) {
412 if (!mContext.getApplicationContext().getResources().getBoolean(
413 com.android.internal.R.bool.config_voice_capable)) {
414 Log.w(this,
415 "registerPhoneAccount not allowed on non-voice capable device.");
416 return;
Ihab Awad8d5d9dd2015-03-12 11:11:06 -0700417 }
Yorke Lee58061752015-05-04 11:06:26 -0700418 try {
Brad Ebinger11623a32015-11-25 13:52:02 -0800419 enforcePhoneAccountModificationForPackage(
420 account.getAccountHandle().getComponentName().getPackageName());
Tyler Gunnacb3bc82017-01-09 09:43:56 -0800421 if (account.hasCapabilities(PhoneAccount.CAPABILITY_SELF_MANAGED)) {
422 enforceRegisterSelfManaged();
Tyler Gunn9e806ee2017-02-06 20:49:24 -0800423 if (account.hasCapabilities(PhoneAccount.CAPABILITY_CALL_PROVIDER) ||
424 account.hasCapabilities(
425 PhoneAccount.CAPABILITY_CONNECTION_MANAGER) ||
426 account.hasCapabilities(
427 PhoneAccount.CAPABILITY_SIM_SUBSCRIPTION)) {
428 throw new SecurityException("Self-managed ConnectionServices " +
429 "cannot also be call capable, connection managers, or " +
430 "SIM accounts.");
431 }
Tyler Gunn2b17f232017-03-08 08:51:00 -0800432
433 // For self-managed CS, the phone account registrar will override the
434 // label the user has set for the phone account. This ensures the
435 // self-managed cs implementation can't spoof their app name.
Tyler Gunnacb3bc82017-01-09 09:43:56 -0800436 }
Brad Ebinger11623a32015-11-25 13:52:02 -0800437 if (account.hasCapabilities(PhoneAccount.CAPABILITY_SIM_SUBSCRIPTION)) {
438 enforceRegisterSimSubscriptionPermission();
439 }
440 if (account.hasCapabilities(PhoneAccount.CAPABILITY_MULTI_USER)) {
441 enforceRegisterMultiUser();
442 }
443 enforceUserHandleMatchesCaller(account.getAccountHandle());
Tyler Gunncbc9be22017-04-19 10:52:36 -0700444 final long token = Binder.clearCallingIdentity();
445 try {
446 mPhoneAccountRegistrar.registerPhoneAccount(account);
447 } finally {
448 Binder.restoreCallingIdentity(token);
449 }
Brad Ebinger11623a32015-11-25 13:52:02 -0800450 } catch (Exception e) {
451 Log.e(this, e, "registerPhoneAccount %s", account);
452 throw e;
Yorke Lee58061752015-05-04 11:06:26 -0700453 }
Ihab Awad8d5d9dd2015-03-12 11:11:06 -0700454 }
Brad Ebinger11623a32015-11-25 13:52:02 -0800455 } finally {
456 Log.endSession();
Santos Cordonf987d1a2014-12-02 03:37:03 -0800457 }
458 }
459
460 @Override
461 public void unregisterPhoneAccount(PhoneAccountHandle accountHandle) {
Ihab Awad8d5d9dd2015-03-12 11:11:06 -0700462 synchronized (mLock) {
463 try {
Brad Ebinger11623a32015-11-25 13:52:02 -0800464 Log.startSession("TSI.uPA");
Ihab Awad8d5d9dd2015-03-12 11:11:06 -0700465 enforcePhoneAccountModificationForPackage(
466 accountHandle.getComponentName().getPackageName());
467 enforceUserHandleMatchesCaller(accountHandle);
Tyler Gunncbc9be22017-04-19 10:52:36 -0700468 final long token = Binder.clearCallingIdentity();
469 try {
470 mPhoneAccountRegistrar.unregisterPhoneAccount(accountHandle);
471 } finally {
472 Binder.restoreCallingIdentity(token);
473 }
Ihab Awad8d5d9dd2015-03-12 11:11:06 -0700474 } catch (Exception e) {
475 Log.e(this, e, "unregisterPhoneAccount %s", accountHandle);
476 throw e;
Brad Ebinger11623a32015-11-25 13:52:02 -0800477 } finally {
478 Log.endSession();
Ihab Awad8d5d9dd2015-03-12 11:11:06 -0700479 }
Santos Cordonf987d1a2014-12-02 03:37:03 -0800480 }
481 }
482
483 @Override
484 public void clearAccounts(String packageName) {
Ihab Awad8d5d9dd2015-03-12 11:11:06 -0700485 synchronized (mLock) {
486 try {
Brad Ebinger11623a32015-11-25 13:52:02 -0800487 Log.startSession("TSI.cA");
Ihab Awad8d5d9dd2015-03-12 11:11:06 -0700488 enforcePhoneAccountModificationForPackage(packageName);
489 mPhoneAccountRegistrar
490 .clearAccounts(packageName, Binder.getCallingUserHandle());
491 } catch (Exception e) {
492 Log.e(this, e, "clearAccounts %s", packageName);
493 throw e;
Brad Ebinger11623a32015-11-25 13:52:02 -0800494 } finally {
495 Log.endSession();
Ihab Awad8d5d9dd2015-03-12 11:11:06 -0700496 }
Santos Cordonf987d1a2014-12-02 03:37:03 -0800497 }
498 }
499
500 /**
501 * @see android.telecom.TelecomManager#isVoiceMailNumber
502 */
503 @Override
Svet Ganov09611182015-04-16 12:29:01 -0700504 public boolean isVoiceMailNumber(PhoneAccountHandle accountHandle, String number,
505 String callingPackage) {
Brad Ebinger11623a32015-11-25 13:52:02 -0800506 try {
507 Log.startSession("TSI.iVMN");
508 synchronized (mLock) {
509 if (!canReadPhoneState(callingPackage, "isVoiceMailNumber")) {
510 return false;
511 }
512 final UserHandle callingUserHandle = Binder.getCallingUserHandle();
513 if (!isPhoneAccountHandleVisibleToCallingUser(accountHandle,
514 callingUserHandle)) {
515 Log.d(this, "%s is not visible for the calling user [iVMN]", accountHandle);
516 return false;
517 }
518 long token = Binder.clearCallingIdentity();
519 try {
520 return mPhoneAccountRegistrar.isVoiceMailNumber(accountHandle, number);
521 } catch (Exception e) {
522 Log.e(this, e, "getSubscriptionIdForPhoneAccount");
523 throw e;
524 } finally {
525 Binder.restoreCallingIdentity(token);
526 }
Svet Ganov09611182015-04-16 12:29:01 -0700527 }
Brad Ebinger11623a32015-11-25 13:52:02 -0800528 } finally {
529 Log.endSession();
Santos Cordonf987d1a2014-12-02 03:37:03 -0800530 }
531 }
532
533 /**
Yorke Leefb5ec302015-04-15 16:15:55 -0700534 * @see android.telecom.TelecomManager#getVoiceMailNumber
Santos Cordonf987d1a2014-12-02 03:37:03 -0800535 */
536 @Override
Svet Ganov09611182015-04-16 12:29:01 -0700537 public String getVoiceMailNumber(PhoneAccountHandle accountHandle, String callingPackage) {
Brad Ebinger11623a32015-11-25 13:52:02 -0800538 try {
539 Log.startSession("TSI.gVMN");
540 synchronized (mLock) {
541 if (!canReadPhoneState(callingPackage, "getVoiceMailNumber")) {
Yorke Leefb5ec302015-04-15 16:15:55 -0700542 return null;
Ihab Awad8d5d9dd2015-03-12 11:11:06 -0700543 }
Brad Ebinger11623a32015-11-25 13:52:02 -0800544 try {
545 final UserHandle callingUserHandle = Binder.getCallingUserHandle();
546 if (!isPhoneAccountHandleVisibleToCallingUser(accountHandle,
547 callingUserHandle)) {
548 Log.d(this, "%s is not visible for the calling user [gVMN]",
549 accountHandle);
550 return null;
551 }
Hall Liu0a6dd302015-12-16 15:06:49 -0800552 int subId = mSubscriptionManagerAdapter.getDefaultVoiceSubId();
Brad Ebinger11623a32015-11-25 13:52:02 -0800553 if (accountHandle != null) {
554 subId = mPhoneAccountRegistrar
555 .getSubscriptionIdForPhoneAccount(accountHandle);
556 }
557 return getTelephonyManager().getVoiceMailNumber(subId);
558 } catch (Exception e) {
559 Log.e(this, e, "getSubscriptionIdForPhoneAccount");
560 throw e;
Ihab Awad8d5d9dd2015-03-12 11:11:06 -0700561 }
Ihab Awad78a5e6b2015-02-06 10:13:05 -0800562 }
Brad Ebinger11623a32015-11-25 13:52:02 -0800563 } finally {
564 Log.endSession();
Santos Cordonf987d1a2014-12-02 03:37:03 -0800565 }
566 }
567
568 /**
Nancy Chenba304752015-01-24 23:29:22 -0800569 * @see android.telecom.TelecomManager#getLine1Number
570 */
571 @Override
Svet Ganov09611182015-04-16 12:29:01 -0700572 public String getLine1Number(PhoneAccountHandle accountHandle, String callingPackage) {
Brad Ebinger11623a32015-11-25 13:52:02 -0800573 try {
574 Log.startSession("getL1N");
575 if (!canReadPhoneState(callingPackage, "getLine1Number")) {
Santos Cordonebf2d0f2015-05-15 10:28:29 -0700576 return null;
577 }
578
Brad Ebinger11623a32015-11-25 13:52:02 -0800579 synchronized (mLock) {
580 final UserHandle callingUserHandle = Binder.getCallingUserHandle();
581 if (!isPhoneAccountHandleVisibleToCallingUser(accountHandle,
582 callingUserHandle)) {
583 Log.d(this, "%s is not visible for the calling user [gL1N]", accountHandle);
584 return null;
585 }
586
587 long token = Binder.clearCallingIdentity();
588 try {
589 int subId = mPhoneAccountRegistrar.getSubscriptionIdForPhoneAccount(
590 accountHandle);
Shishir Agrawalce688742016-01-25 15:02:21 -0800591 return getTelephonyManager().getLine1Number(subId);
Brad Ebinger11623a32015-11-25 13:52:02 -0800592 } catch (Exception e) {
593 Log.e(this, e, "getSubscriptionIdForPhoneAccount");
594 throw e;
595 } finally {
596 Binder.restoreCallingIdentity(token);
597 }
Nancy Chenba304752015-01-24 23:29:22 -0800598 }
Brad Ebinger11623a32015-11-25 13:52:02 -0800599 } finally {
600 Log.endSession();
Nancy Chenba304752015-01-24 23:29:22 -0800601 }
602 }
603
604 /**
Santos Cordonf987d1a2014-12-02 03:37:03 -0800605 * @see android.telecom.TelecomManager#silenceRinger
606 */
607 @Override
Yorke Lee53101962015-04-29 16:25:29 -0700608 public void silenceRinger(String callingPackage) {
Brad Ebinger11623a32015-11-25 13:52:02 -0800609 try {
610 Log.startSession("TSI.sR");
611 synchronized (mLock) {
612 enforcePermissionOrPrivilegedDialer(MODIFY_PHONE_STATE, callingPackage);
Santos Cordonebf2d0f2015-05-15 10:28:29 -0700613
Brad Ebinger11623a32015-11-25 13:52:02 -0800614 long token = Binder.clearCallingIdentity();
615 try {
616 Log.i(this, "Silence Ringer requested by %s", callingPackage);
Hall Liue091ab92015-12-18 17:05:30 -0800617 mCallsManager.getCallAudioManager().silenceRingers();
Sailesh Nepalc07b8e12016-01-23 16:43:10 -0800618 mCallsManager.getInCallController().silenceRinger();
Brad Ebinger11623a32015-11-25 13:52:02 -0800619 } finally {
620 Binder.restoreCallingIdentity(token);
621 }
Santos Cordonebf2d0f2015-05-15 10:28:29 -0700622 }
Brad Ebinger11623a32015-11-25 13:52:02 -0800623 } finally {
624 Log.endSession();
Ihab Awad8d5d9dd2015-03-12 11:11:06 -0700625 }
Santos Cordonf987d1a2014-12-02 03:37:03 -0800626 }
627
628 /**
629 * @see android.telecom.TelecomManager#getDefaultPhoneApp
Yorke Lee5b3fc0a2015-04-23 17:42:57 -0700630 * @deprecated - Use {@link android.telecom.TelecomManager#getDefaultDialerPackage()}
631 * instead.
Santos Cordonf987d1a2014-12-02 03:37:03 -0800632 */
633 @Override
634 public ComponentName getDefaultPhoneApp() {
Brad Ebinger11623a32015-11-25 13:52:02 -0800635 try {
636 Log.startSession("TSI.gDPA");
637 // No need to synchronize
638 Resources resources = mContext.getResources();
639 return new ComponentName(
640 resources.getString(R.string.ui_default_package),
641 resources.getString(R.string.dialer_default_class));
642 } finally {
643 Log.endSession();
644 }
Santos Cordonf987d1a2014-12-02 03:37:03 -0800645 }
646
647 /**
Yorke Lee5291d4a2015-04-24 16:42:36 -0700648 * @return the package name of the current user-selected default dialer. If no default
649 * has been selected, the package name of the system dialer is returned. If
650 * neither exists, then {@code null} is returned.
Yorke Lee5b3fc0a2015-04-23 17:42:57 -0700651 * @see android.telecom.TelecomManager#getDefaultDialerPackage
652 */
653 @Override
654 public String getDefaultDialerPackage() {
Yorke Lee29c003e2015-05-04 17:09:27 -0700655 try {
Brad Ebinger11623a32015-11-25 13:52:02 -0800656 Log.startSession("TSI.gDDP");
657 final long token = Binder.clearCallingIdentity();
658 try {
Hall Liu7c928322016-12-06 18:15:39 -0800659 return mDefaultDialerCache.getDefaultDialerApplication(
660 ActivityManager.getCurrentUser());
Brad Ebinger11623a32015-11-25 13:52:02 -0800661 } finally {
662 Binder.restoreCallingIdentity(token);
663 }
Yorke Lee29c003e2015-05-04 17:09:27 -0700664 } finally {
Brad Ebinger11623a32015-11-25 13:52:02 -0800665 Log.endSession();
Yorke Lee29c003e2015-05-04 17:09:27 -0700666 }
Yorke Lee5b3fc0a2015-04-23 17:42:57 -0700667 }
668
669 /**
670 * @see android.telecom.TelecomManager#getSystemDialerPackage
671 */
672 @Override
673 public String getSystemDialerPackage() {
Brad Ebinger11623a32015-11-25 13:52:02 -0800674 try {
675 Log.startSession("TSI.gSDP");
676 return mContext.getResources().getString(R.string.ui_default_package);
677 } finally {
678 Log.endSession();
679 }
Yorke Lee5b3fc0a2015-04-23 17:42:57 -0700680 }
681
682 /**
Santos Cordonf987d1a2014-12-02 03:37:03 -0800683 * @see android.telecom.TelecomManager#isInCall
684 */
685 @Override
Svet Ganov09611182015-04-16 12:29:01 -0700686 public boolean isInCall(String callingPackage) {
Brad Ebinger11623a32015-11-25 13:52:02 -0800687 try {
688 Log.startSession("TSI.iIC");
689 if (!canReadPhoneState(callingPackage, "isInCall")) {
690 return false;
691 }
Svet Ganov09611182015-04-16 12:29:01 -0700692
Brad Ebinger11623a32015-11-25 13:52:02 -0800693 synchronized (mLock) {
Tyler Gunnbaf105b2017-04-11 15:21:03 -0700694 return mCallsManager.hasOngoingCalls();
Brad Ebinger11623a32015-11-25 13:52:02 -0800695 }
696 } finally {
697 Log.endSession();
Ihab Awad8d5d9dd2015-03-12 11:11:06 -0700698 }
Santos Cordonf987d1a2014-12-02 03:37:03 -0800699 }
700
701 /**
Tyler Gunn37e782b2017-02-10 09:42:03 -0800702 * @see android.telecom.TelecomManager#isInManagedCall
703 */
704 @Override
705 public boolean isInManagedCall(String callingPackage) {
706 try {
707 Log.startSession("TSI.iIMC");
708 if (!canReadPhoneState(callingPackage, "isInManagedCall")) {
709 throw new SecurityException("Only the default dialer or caller with " +
710 "READ_PHONE_STATE permission can use this method.");
711 }
712
713 synchronized (mLock) {
714 return mCallsManager.hasOngoingManagedCalls();
715 }
716 } finally {
717 Log.endSession();
718 }
719 }
720
721 /**
Santos Cordonf987d1a2014-12-02 03:37:03 -0800722 * @see android.telecom.TelecomManager#isRinging
723 */
724 @Override
Svet Ganov09611182015-04-16 12:29:01 -0700725 public boolean isRinging(String callingPackage) {
Brad Ebinger11623a32015-11-25 13:52:02 -0800726 try {
727 Log.startSession("TSI.iR");
Tyler Gunn322480c2017-07-17 15:34:02 -0700728 if (!isPrivilegedDialerCalling(callingPackage)) {
729 try {
730 enforceModifyPermission(
731 "isRinging requires MODIFY_PHONE_STATE permission.");
732 } catch (SecurityException e) {
733 EventLog.writeEvent(0x534e4554, "62347125", "isRinging: " + callingPackage);
734 throw e;
735 }
Brad Ebinger11623a32015-11-25 13:52:02 -0800736 }
Svet Ganov09611182015-04-16 12:29:01 -0700737
Brad Ebinger11623a32015-11-25 13:52:02 -0800738 synchronized (mLock) {
739 // Note: We are explicitly checking the calls telecom is tracking rather than
740 // relying on mCallsManager#getCallState(). Since getCallState() relies on the
741 // current state as tracked by PhoneStateBroadcaster, any failure to properly
742 // track the current call state there could result in the wrong ringing state
743 // being reported by this API.
744 return mCallsManager.hasRingingCall();
745 }
746 } finally {
747 Log.endSession();
Ihab Awad8d5d9dd2015-03-12 11:11:06 -0700748 }
Santos Cordonf987d1a2014-12-02 03:37:03 -0800749 }
750
751 /**
752 * @see TelecomManager#getCallState
753 */
754 @Override
755 public int getCallState() {
Brad Ebinger11623a32015-11-25 13:52:02 -0800756 try {
757 Log.startSession("TSI.getCallState");
758 synchronized (mLock) {
759 return mCallsManager.getCallState();
760 }
761 } finally {
762 Log.endSession();
Ihab Awad8d5d9dd2015-03-12 11:11:06 -0700763 }
Santos Cordonf987d1a2014-12-02 03:37:03 -0800764 }
765
766 /**
767 * @see android.telecom.TelecomManager#endCall
768 */
769 @Override
Tyler Gunn587fc272018-02-07 16:07:29 -0800770 public boolean endCall(String callingPackage) {
Brad Ebinger11623a32015-11-25 13:52:02 -0800771 try {
772 Log.startSession("TSI.eC");
773 synchronized (mLock) {
774 enforceModifyPermission();
Santos Cordonebf2d0f2015-05-15 10:28:29 -0700775
Brad Ebinger11623a32015-11-25 13:52:02 -0800776 long token = Binder.clearCallingIdentity();
777 try {
Tyler Gunn587fc272018-02-07 16:07:29 -0800778 return endCallInternal(callingPackage);
Brad Ebinger11623a32015-11-25 13:52:02 -0800779 } finally {
780 Binder.restoreCallingIdentity(token);
781 }
Santos Cordonebf2d0f2015-05-15 10:28:29 -0700782 }
Brad Ebinger11623a32015-11-25 13:52:02 -0800783 } finally {
784 Log.endSession();
Ihab Awad8d5d9dd2015-03-12 11:11:06 -0700785 }
Santos Cordonf987d1a2014-12-02 03:37:03 -0800786 }
787
788 /**
789 * @see android.telecom.TelecomManager#acceptRingingCall
790 */
791 @Override
Eugene Suslaccba7202017-02-10 10:56:53 -0800792 public void acceptRingingCall(String packageName) {
Brad Ebinger11623a32015-11-25 13:52:02 -0800793 try {
794 Log.startSession("TSI.aRC");
795 synchronized (mLock) {
Eugene Suslaccba7202017-02-10 10:56:53 -0800796 if (!enforceAnswerCallPermission(packageName, Binder.getCallingUid())) return;
Santos Cordonebf2d0f2015-05-15 10:28:29 -0700797
Brad Ebinger11623a32015-11-25 13:52:02 -0800798 long token = Binder.clearCallingIdentity();
799 try {
800 acceptRingingCallInternal(DEFAULT_VIDEO_STATE);
801 } finally {
802 Binder.restoreCallingIdentity(token);
803 }
Tyler Gunn42ef8082015-11-24 15:34:34 -0800804 }
Brad Ebinger11623a32015-11-25 13:52:02 -0800805 } finally {
806 Log.endSession();
Tyler Gunn42ef8082015-11-24 15:34:34 -0800807 }
808 }
809
810 /**
811 * @see android.telecom.TelecomManager#acceptRingingCall(int)
812 *
813 */
814 @Override
Eugene Suslaccba7202017-02-10 10:56:53 -0800815 public void acceptRingingCallWithVideoState(String packageName, int videoState) {
Brad Ebinger11623a32015-11-25 13:52:02 -0800816 try {
817 Log.startSession("TSI.aRCWVS");
818 synchronized (mLock) {
Eugene Suslaccba7202017-02-10 10:56:53 -0800819 if (!enforceAnswerCallPermission(packageName, Binder.getCallingUid())) return;
Tyler Gunn42ef8082015-11-24 15:34:34 -0800820
Brad Ebinger11623a32015-11-25 13:52:02 -0800821 long token = Binder.clearCallingIdentity();
822 try {
823 acceptRingingCallInternal(videoState);
824 } finally {
825 Binder.restoreCallingIdentity(token);
826 }
Santos Cordonebf2d0f2015-05-15 10:28:29 -0700827 }
Brad Ebinger11623a32015-11-25 13:52:02 -0800828 } finally {
829 Log.endSession();
Ihab Awad8d5d9dd2015-03-12 11:11:06 -0700830 }
Santos Cordonf987d1a2014-12-02 03:37:03 -0800831 }
832
833 /**
834 * @see android.telecom.TelecomManager#showInCallScreen
835 */
836 @Override
Svet Ganov09611182015-04-16 12:29:01 -0700837 public void showInCallScreen(boolean showDialpad, String callingPackage) {
Brad Ebinger11623a32015-11-25 13:52:02 -0800838 try {
839 Log.startSession("TSI.sICS");
840 if (!canReadPhoneState(callingPackage, "showInCallScreen")) {
841 return;
Santos Cordonebf2d0f2015-05-15 10:28:29 -0700842 }
Brad Ebinger11623a32015-11-25 13:52:02 -0800843
844 synchronized (mLock) {
845
846 long token = Binder.clearCallingIdentity();
847 try {
848 mCallsManager.getInCallController().bringToForeground(showDialpad);
849 } finally {
850 Binder.restoreCallingIdentity(token);
851 }
852 }
853 } finally {
854 Log.endSession();
Ihab Awad8d5d9dd2015-03-12 11:11:06 -0700855 }
Santos Cordonf987d1a2014-12-02 03:37:03 -0800856 }
857
858 /**
859 * @see android.telecom.TelecomManager#cancelMissedCallsNotification
860 */
861 @Override
Yorke Lee53101962015-04-29 16:25:29 -0700862 public void cancelMissedCallsNotification(String callingPackage) {
Brad Ebinger11623a32015-11-25 13:52:02 -0800863 try {
864 Log.startSession("TSI.cMCN");
865 synchronized (mLock) {
866 enforcePermissionOrPrivilegedDialer(MODIFY_PHONE_STATE, callingPackage);
Tony Maka9930942016-01-15 10:57:14 +0000867 UserHandle userHandle = Binder.getCallingUserHandle();
Brad Ebinger11623a32015-11-25 13:52:02 -0800868 long token = Binder.clearCallingIdentity();
869 try {
Tony Maka9930942016-01-15 10:57:14 +0000870 mCallsManager.getMissedCallNotifier().clearMissedCalls(userHandle);
Brad Ebinger11623a32015-11-25 13:52:02 -0800871 } finally {
872 Binder.restoreCallingIdentity(token);
873 }
Santos Cordonebf2d0f2015-05-15 10:28:29 -0700874 }
Brad Ebinger11623a32015-11-25 13:52:02 -0800875 } finally {
876 Log.endSession();
Ihab Awad8d5d9dd2015-03-12 11:11:06 -0700877 }
Santos Cordonf987d1a2014-12-02 03:37:03 -0800878 }
Santos Cordonf987d1a2014-12-02 03:37:03 -0800879 /**
880 * @see android.telecom.TelecomManager#handleMmi
881 */
882 @Override
Yorke Lee53101962015-04-29 16:25:29 -0700883 public boolean handlePinMmi(String dialString, String callingPackage) {
Brad Ebinger11623a32015-11-25 13:52:02 -0800884 try {
885 Log.startSession("TSI.hPM");
886 synchronized (mLock) {
887 enforcePermissionOrPrivilegedDialer(MODIFY_PHONE_STATE, callingPackage);
Santos Cordonf987d1a2014-12-02 03:37:03 -0800888
Brad Ebinger11623a32015-11-25 13:52:02 -0800889 // Switch identity so that TelephonyManager checks Telecom's permissions
890 // instead.
891 long token = Binder.clearCallingIdentity();
892 boolean retval = false;
893 try {
894 retval = getTelephonyManager().handlePinMmi(dialString);
895 } finally {
896 Binder.restoreCallingIdentity(token);
897 }
898
899 return retval;
Ihab Awad8d5d9dd2015-03-12 11:11:06 -0700900 }
Brad Ebinger11623a32015-11-25 13:52:02 -0800901 }finally {
902 Log.endSession();
Santos Cordonf987d1a2014-12-02 03:37:03 -0800903 }
Santos Cordonf987d1a2014-12-02 03:37:03 -0800904 }
905
906 /**
907 * @see android.telecom.TelecomManager#handleMmi
908 */
909 @Override
Brad Ebinger11623a32015-11-25 13:52:02 -0800910 public boolean handlePinMmiForPhoneAccount(PhoneAccountHandle accountHandle,
911 String dialString, String callingPackage) {
912 try {
913 Log.startSession("TSI.hPMFPA");
914 synchronized (mLock) {
915 enforcePermissionOrPrivilegedDialer(MODIFY_PHONE_STATE, callingPackage);
Santos Cordonf987d1a2014-12-02 03:37:03 -0800916
Brad Ebinger11623a32015-11-25 13:52:02 -0800917 UserHandle callingUserHandle = Binder.getCallingUserHandle();
918 if (!isPhoneAccountHandleVisibleToCallingUser(accountHandle,
919 callingUserHandle)) {
920 Log.d(this, "%s is not visible for the calling user [hMMI]", accountHandle);
921 return false;
922 }
923
924 // Switch identity so that TelephonyManager checks Telecom's permissions
925 // instead.
926 long token = Binder.clearCallingIdentity();
927 boolean retval = false;
928 try {
929 int subId = mPhoneAccountRegistrar.getSubscriptionIdForPhoneAccount(
930 accountHandle);
931 retval = getTelephonyManager().handlePinMmiForSubscriber(subId, dialString);
932 } finally {
933 Binder.restoreCallingIdentity(token);
934 }
935 return retval;
Ihab Awad8d5d9dd2015-03-12 11:11:06 -0700936 }
Brad Ebinger11623a32015-11-25 13:52:02 -0800937 }finally {
938 Log.endSession();
Santos Cordonf987d1a2014-12-02 03:37:03 -0800939 }
Santos Cordonf987d1a2014-12-02 03:37:03 -0800940 }
941
942 /**
943 * @see android.telecom.TelecomManager#getAdnUriForPhoneAccount
944 */
945 @Override
Yorke Lee53101962015-04-29 16:25:29 -0700946 public Uri getAdnUriForPhoneAccount(PhoneAccountHandle accountHandle,
947 String callingPackage) {
Brad Ebinger11623a32015-11-25 13:52:02 -0800948 try {
949 Log.startSession("TSI.aAUFPA");
950 synchronized (mLock) {
951 enforcePermissionOrPrivilegedDialer(MODIFY_PHONE_STATE, callingPackage);
952 if (!isPhoneAccountHandleVisibleToCallingUser(accountHandle,
953 Binder.getCallingUserHandle())) {
954 Log.d(this, "%s is not visible for the calling user [gA4PA]",
955 accountHandle);
956 return null;
957 }
958 // Switch identity so that TelephonyManager checks Telecom's permissions
959 // instead.
960 long token = Binder.clearCallingIdentity();
961 String retval = "content://icc/adn/";
962 try {
963 long subId = mPhoneAccountRegistrar
964 .getSubscriptionIdForPhoneAccount(accountHandle);
965 retval = retval + "subId/" + subId;
966 } finally {
967 Binder.restoreCallingIdentity(token);
968 }
Ihab Awad8d5d9dd2015-03-12 11:11:06 -0700969
Brad Ebinger11623a32015-11-25 13:52:02 -0800970 return Uri.parse(retval);
Ihab Awad8d5d9dd2015-03-12 11:11:06 -0700971 }
Brad Ebinger11623a32015-11-25 13:52:02 -0800972 } finally {
973 Log.endSession();
Santos Cordonf987d1a2014-12-02 03:37:03 -0800974 }
Santos Cordonf987d1a2014-12-02 03:37:03 -0800975 }
976
977 /**
978 * @see android.telecom.TelecomManager#isTtySupported
979 */
980 @Override
Svet Ganov09611182015-04-16 12:29:01 -0700981 public boolean isTtySupported(String callingPackage) {
Brad Ebinger11623a32015-11-25 13:52:02 -0800982 try {
983 Log.startSession("TSI.iTS");
Sanket Padawe88efa0c2017-09-08 11:46:34 -0700984 if (!canReadPhoneState(callingPackage, "isTtySupported")) {
985 throw new SecurityException("Only default dialer or an app with" +
986 "READ_PRIVILEGED_PHONE_STATE or READ_PHONE_STATE can call this api");
Brad Ebinger11623a32015-11-25 13:52:02 -0800987 }
Svet Ganov09611182015-04-16 12:29:01 -0700988
Brad Ebinger11623a32015-11-25 13:52:02 -0800989 synchronized (mLock) {
990 return mCallsManager.isTtySupported();
991 }
992 } finally {
993 Log.endSession();
Ihab Awad8d5d9dd2015-03-12 11:11:06 -0700994 }
Santos Cordonf987d1a2014-12-02 03:37:03 -0800995 }
996
997 /**
998 * @see android.telecom.TelecomManager#getCurrentTtyMode
999 */
1000 @Override
Svet Ganov09611182015-04-16 12:29:01 -07001001 public int getCurrentTtyMode(String callingPackage) {
Brad Ebinger11623a32015-11-25 13:52:02 -08001002 try {
1003 Log.startSession("TSI.gCTM");
1004 if (!canReadPhoneState(callingPackage, "getCurrentTtyMode")) {
1005 return TelecomManager.TTY_MODE_OFF;
1006 }
Svet Ganov09611182015-04-16 12:29:01 -07001007
Brad Ebinger11623a32015-11-25 13:52:02 -08001008 synchronized (mLock) {
1009 return mCallsManager.getCurrentTtyMode();
1010 }
1011 } finally {
1012 Log.endSession();
Ihab Awad8d5d9dd2015-03-12 11:11:06 -07001013 }
Santos Cordonf987d1a2014-12-02 03:37:03 -08001014 }
1015
1016 /**
1017 * @see android.telecom.TelecomManager#addNewIncomingCall
1018 */
1019 @Override
1020 public void addNewIncomingCall(PhoneAccountHandle phoneAccountHandle, Bundle extras) {
Brad Ebinger11623a32015-11-25 13:52:02 -08001021 try {
1022 Log.startSession("TSI.aNIC");
1023 synchronized (mLock) {
1024 Log.i(this, "Adding new incoming call with phoneAccountHandle %s",
Sharvil Nanavati6d3efb42015-05-14 11:36:40 -07001025 phoneAccountHandle);
Brad Ebinger11623a32015-11-25 13:52:02 -08001026 if (phoneAccountHandle != null &&
1027 phoneAccountHandle.getComponentName() != null) {
1028 // TODO(sail): Add unit tests for adding incoming calls from a SIM call
1029 // manager.
1030 if (isCallerSimCallManager() && TelephonyUtil.isPstnComponentName(
1031 phoneAccountHandle.getComponentName())) {
1032 Log.v(this, "Allowing call manager to add incoming call with PSTN" +
1033 " handle");
1034 } else {
1035 mAppOpsManager.checkPackage(
1036 Binder.getCallingUid(),
1037 phoneAccountHandle.getComponentName().getPackageName());
1038 // Make sure it doesn't cross the UserHandle boundary
1039 enforceUserHandleMatchesCaller(phoneAccountHandle);
Tony Mak5851fa02016-02-23 19:41:52 +00001040 enforcePhoneAccountIsRegisteredEnabled(phoneAccountHandle,
1041 Binder.getCallingUserHandle());
Tyler Gunna90ba732017-01-26 07:24:08 -08001042 if (isSelfManagedConnectionService(phoneAccountHandle)) {
1043 // Self-managed phone account, ensure it has MANAGE_OWN_CALLS.
1044 mContext.enforceCallingOrSelfPermission(
1045 android.Manifest.permission.MANAGE_OWN_CALLS,
1046 "Self-managed phone accounts must have MANAGE_OWN_CALLS " +
1047 "permission.");
Tyler Gunn0c7cf9a2017-05-17 11:15:57 -07001048
1049 // Self-managed ConnectionServices can ONLY add new incoming calls
1050 // using their own PhoneAccounts. The checkPackage(..) app opps
1051 // check above ensures this.
Tyler Gunna90ba732017-01-26 07:24:08 -08001052 }
Sharvil Nanavati6d3efb42015-05-14 11:36:40 -07001053 }
Brad Ebinger11623a32015-11-25 13:52:02 -08001054 long token = Binder.clearCallingIdentity();
1055 try {
1056 Intent intent = new Intent(TelecomManager.ACTION_INCOMING_CALL);
1057 intent.putExtra(TelecomManager.EXTRA_PHONE_ACCOUNT_HANDLE,
1058 phoneAccountHandle);
1059 intent.putExtra(CallIntentProcessor.KEY_IS_INCOMING_CALL, true);
1060 if (extras != null) {
Jeff Sharkeye2e4cdf2016-03-18 12:19:02 -06001061 extras.setDefusable(true);
Brad Ebinger11623a32015-11-25 13:52:02 -08001062 intent.putExtra(TelecomManager.EXTRA_INCOMING_CALL_EXTRAS, extras);
1063 }
Hall Liuecda5542015-12-04 11:31:31 -08001064 mCallIntentProcessorAdapter.processIncomingCallIntent(
1065 mCallsManager, intent);
Brad Ebinger11623a32015-11-25 13:52:02 -08001066 } finally {
1067 Binder.restoreCallingIdentity(token);
1068 }
1069 } else {
1070 Log.w(this, "Null phoneAccountHandle. Ignoring request to add new" +
1071 " incoming call");
Ihab Awad8d5d9dd2015-03-12 11:11:06 -07001072 }
Santos Cordonf987d1a2014-12-02 03:37:03 -08001073 }
Brad Ebinger11623a32015-11-25 13:52:02 -08001074 } finally {
1075 Log.endSession();
Santos Cordonf987d1a2014-12-02 03:37:03 -08001076 }
1077 }
1078
1079 /**
Sanket Padaweccdf3642017-11-10 14:49:05 -08001080 * @see android.telecom.TelecomManager#acceptHandover
1081 */
1082 @Override
1083 public void acceptHandover(Uri srcAddr, int videoState, PhoneAccountHandle destAcct) {
1084 try {
1085 Log.startSession("TSI.aHO");
1086 synchronized (mLock) {
Tyler Gunn37a4dca2018-01-18 15:00:41 -08001087 Log.i(this, "acceptHandover; srcAddr=%s, videoState=%s, dest=%s",
1088 Log.pii(srcAddr), VideoProfile.videoStateToString(videoState),
Sanket Padaweccdf3642017-11-10 14:49:05 -08001089 destAcct);
Tyler Gunn37a4dca2018-01-18 15:00:41 -08001090
Sanket Padaweccdf3642017-11-10 14:49:05 -08001091 if (destAcct != null && destAcct.getComponentName() != null) {
1092 mAppOpsManager.checkPackage(
1093 Binder.getCallingUid(),
1094 destAcct.getComponentName().getPackageName());
1095 enforceUserHandleMatchesCaller(destAcct);
1096 enforcePhoneAccountIsRegisteredEnabled(destAcct,
1097 Binder.getCallingUserHandle());
1098 if (isSelfManagedConnectionService(destAcct)) {
1099 // Self-managed phone account, ensure it has MANAGE_OWN_CALLS.
1100 mContext.enforceCallingOrSelfPermission(
1101 android.Manifest.permission.MANAGE_OWN_CALLS,
1102 "Self-managed phone accounts must have MANAGE_OWN_CALLS " +
1103 "permission.");
1104 }
Tyler Gunn37a4dca2018-01-18 15:00:41 -08001105 if (!enforceAcceptHandoverPermission(
1106 destAcct.getComponentName().getPackageName(),
1107 Binder.getCallingUid())) {
1108 throw new SecurityException("App must be granted runtime "
1109 + "ACCEPT_HANDOVER permission.");
1110 }
Sanket Padaweccdf3642017-11-10 14:49:05 -08001111
Tyler Gunn37a4dca2018-01-18 15:00:41 -08001112 long token = Binder.clearCallingIdentity();
1113 try {
1114 mCallsManager.acceptHandover(srcAddr, videoState, destAcct);
1115 } finally {
1116 Binder.restoreCallingIdentity(token);
1117 }
Sanket Padaweccdf3642017-11-10 14:49:05 -08001118 } else {
1119 Log.w(this, "Null phoneAccountHandle. Ignoring request " +
1120 "to handover the call");
1121 }
1122 }
1123 } finally {
1124 Log.endSession();
1125 }
1126 }
1127
1128 /**
Santos Cordonf987d1a2014-12-02 03:37:03 -08001129 * @see android.telecom.TelecomManager#addNewUnknownCall
1130 */
1131 @Override
1132 public void addNewUnknownCall(PhoneAccountHandle phoneAccountHandle, Bundle extras) {
Brad Ebinger11623a32015-11-25 13:52:02 -08001133 try {
1134 Log.startSession("TSI.aNUC");
Tyler Gunn322480c2017-07-17 15:34:02 -07001135 try {
1136 enforceModifyPermission(
1137 "addNewUnknownCall requires MODIFY_PHONE_STATE permission.");
1138 } catch (SecurityException e) {
1139 EventLog.writeEvent(0x534e4554, "62347125", Binder.getCallingUid(),
1140 "addNewUnknownCall");
1141 throw e;
1142 }
1143
Brad Ebinger11623a32015-11-25 13:52:02 -08001144 synchronized (mLock) {
1145 if (phoneAccountHandle != null &&
1146 phoneAccountHandle.getComponentName() != null) {
1147 mAppOpsManager.checkPackage(
1148 Binder.getCallingUid(),
1149 phoneAccountHandle.getComponentName().getPackageName());
Santos Cordonf987d1a2014-12-02 03:37:03 -08001150
Brad Ebinger11623a32015-11-25 13:52:02 -08001151 // Make sure it doesn't cross the UserHandle boundary
1152 enforceUserHandleMatchesCaller(phoneAccountHandle);
Tony Mak5851fa02016-02-23 19:41:52 +00001153 enforcePhoneAccountIsRegisteredEnabled(phoneAccountHandle,
1154 Binder.getCallingUserHandle());
Brad Ebinger11623a32015-11-25 13:52:02 -08001155 long token = Binder.clearCallingIdentity();
Santos Cordonf987d1a2014-12-02 03:37:03 -08001156
Brad Ebinger11623a32015-11-25 13:52:02 -08001157 try {
1158 Intent intent = new Intent(TelecomManager.ACTION_NEW_UNKNOWN_CALL);
Jeff Sharkeye2e4cdf2016-03-18 12:19:02 -06001159 if (extras != null) {
1160 extras.setDefusable(true);
1161 intent.putExtras(extras);
1162 }
Brad Ebinger11623a32015-11-25 13:52:02 -08001163 intent.putExtra(CallIntentProcessor.KEY_IS_UNKNOWN_CALL, true);
1164 intent.putExtra(TelecomManager.EXTRA_PHONE_ACCOUNT_HANDLE,
1165 phoneAccountHandle);
Hall Liuecda5542015-12-04 11:31:31 -08001166 mCallIntentProcessorAdapter.processUnknownCallIntent(mCallsManager, intent);
Brad Ebinger11623a32015-11-25 13:52:02 -08001167 } finally {
1168 Binder.restoreCallingIdentity(token);
1169 }
1170 } else {
1171 Log.i(this,
1172 "Null phoneAccountHandle or not initiated by Telephony. " +
1173 "Ignoring request to add new unknown call.");
Sharvil Nanavati6d3efb42015-05-14 11:36:40 -07001174 }
Ihab Awad8d5d9dd2015-03-12 11:11:06 -07001175 }
Brad Ebinger11623a32015-11-25 13:52:02 -08001176 } finally {
1177 Log.endSession();
Santos Cordonf987d1a2014-12-02 03:37:03 -08001178 }
1179 }
Tyler Gunn47689862014-12-17 17:10:28 -08001180
1181 /**
Yorke Leea3a3adc2015-04-23 12:49:01 -07001182 * @see android.telecom.TelecomManager#placeCall
1183 */
1184 @Override
1185 public void placeCall(Uri handle, Bundle extras, String callingPackage) {
Brad Ebinger11623a32015-11-25 13:52:02 -08001186 try {
1187 Log.startSession("TSI.pC");
1188 enforceCallingPackage(callingPackage);
Tyler Gunna90ba732017-01-26 07:24:08 -08001189
1190 PhoneAccountHandle phoneAccountHandle = null;
1191 if (extras != null) {
1192 phoneAccountHandle = extras.getParcelable(
1193 TelecomManager.EXTRA_PHONE_ACCOUNT_HANDLE);
Tyler Gunn141ef582017-05-26 13:38:13 -07001194 if (extras.containsKey(TelecomManager.EXTRA_IS_HANDOVER)) {
1195 // This extra is for Telecom use only so should never be passed in.
1196 extras.remove(TelecomManager.EXTRA_IS_HANDOVER);
1197 }
Tyler Gunna90ba732017-01-26 07:24:08 -08001198 }
1199 boolean isSelfManaged = phoneAccountHandle != null &&
1200 isSelfManagedConnectionService(phoneAccountHandle);
1201 if (isSelfManaged) {
1202 mContext.enforceCallingOrSelfPermission(Manifest.permission.MANAGE_OWN_CALLS,
1203 "Self-managed ConnectionServices require MANAGE_OWN_CALLS permission.");
Tyler Gunn0c7cf9a2017-05-17 11:15:57 -07001204
1205 if (!callingPackage.equals(
1206 phoneAccountHandle.getComponentName().getPackageName())
1207 && !canCallPhone(callingPackage,
1208 "CALL_PHONE permission required to place calls.")) {
1209 // The caller is not allowed to place calls, so we want to ensure that it
1210 // can only place calls through itself.
1211 throw new SecurityException("Self-managed ConnectionServices can only "
1212 + "place calls through their own ConnectionService.");
1213 }
Tyler Gunna90ba732017-01-26 07:24:08 -08001214 } else if (!canCallPhone(callingPackage, "placeCall")) {
Brad Ebinger11623a32015-11-25 13:52:02 -08001215 throw new SecurityException("Package " + callingPackage
1216 + " is not allowed to place phone calls");
Yorke Lee58061752015-05-04 11:06:26 -07001217 }
Brad Ebinger11623a32015-11-25 13:52:02 -08001218
1219 // Note: we can still get here for the default/system dialer, even if the Phone
1220 // permission is turned off. This is because the default/system dialer is always
1221 // allowed to attempt to place a call (regardless of permission state), in case
1222 // it turns out to be an emergency call. If the permission is denied and the
1223 // call is being made to a non-emergency number, the call will be denied later on
1224 // by {@link UserCallIntentProcessor}.
1225
1226 final boolean hasCallAppOp = mAppOpsManager.noteOp(AppOpsManager.OP_CALL_PHONE,
1227 Binder.getCallingUid(), callingPackage) == AppOpsManager.MODE_ALLOWED;
1228
1229 final boolean hasCallPermission = mContext.checkCallingPermission(CALL_PHONE) ==
1230 PackageManager.PERMISSION_GRANTED;
Tyler Gunnb652dad2018-03-27 18:49:49 +00001231 // The Emergency Dialer has call privileged permission and uses this to place
1232 // emergency calls. We ensure permission checks in
1233 // NewOutgoingCallIntentBroadcaster#process pass by sending this to
1234 // Telecom as an ACTION_CALL_PRIVILEGED intent (which makes sense since the
1235 // com.android.phone process has that permission).
1236 final boolean hasCallPrivilegedPermission = mContext.checkCallingPermission(
1237 CALL_PRIVILEGED) == PackageManager.PERMISSION_GRANTED;
Brad Ebinger11623a32015-11-25 13:52:02 -08001238
1239 synchronized (mLock) {
1240 final UserHandle userHandle = Binder.getCallingUserHandle();
1241 long token = Binder.clearCallingIdentity();
1242 try {
Tyler Gunnb652dad2018-03-27 18:49:49 +00001243 final Intent intent = new Intent(hasCallPrivilegedPermission ?
1244 Intent.ACTION_CALL_PRIVILEGED : Intent.ACTION_CALL, handle);
Jeff Sharkeye2e4cdf2016-03-18 12:19:02 -06001245 if (extras != null) {
1246 extras.setDefusable(true);
1247 intent.putExtras(extras);
1248 }
Hall Liuecda5542015-12-04 11:31:31 -08001249 mUserCallIntentProcessorFactory.create(mContext, userHandle)
1250 .processIntent(
Tyler Gunna90ba732017-01-26 07:24:08 -08001251 intent, callingPackage, isSelfManaged ||
Tyler Gunnb652dad2018-03-27 18:49:49 +00001252 (hasCallAppOp && hasCallPermission),
1253 true /* isLocalInvocation */);
Brad Ebinger11623a32015-11-25 13:52:02 -08001254 } finally {
1255 Binder.restoreCallingIdentity(token);
1256 }
1257 }
1258 } finally {
1259 Log.endSession();
Yorke Leea3a3adc2015-04-23 12:49:01 -07001260 }
1261 }
1262
1263 /**
Santos Cordonea5cb932015-05-07 16:28:38 -07001264 * @see android.telecom.TelecomManager#enablePhoneAccount
1265 */
1266 @Override
Yorke Lee71734c22015-06-02 14:22:56 -07001267 public boolean enablePhoneAccount(PhoneAccountHandle accountHandle, boolean isEnabled) {
Brad Ebinger11623a32015-11-25 13:52:02 -08001268 try {
1269 Log.startSession("TSI.ePA");
1270 enforceModifyPermission();
1271 synchronized (mLock) {
1272 long token = Binder.clearCallingIdentity();
1273 try {
1274 // enable/disable phone account
1275 return mPhoneAccountRegistrar.enablePhoneAccount(accountHandle, isEnabled);
1276 } finally {
1277 Binder.restoreCallingIdentity(token);
1278 }
Yorke Lee71734c22015-06-02 14:22:56 -07001279 }
Brad Ebinger11623a32015-11-25 13:52:02 -08001280 } finally {
1281 Log.endSession();
Yorke Lee71734c22015-06-02 14:22:56 -07001282 }
1283 }
1284
1285 @Override
1286 public boolean setDefaultDialer(String packageName) {
Brad Ebinger11623a32015-11-25 13:52:02 -08001287 try {
1288 Log.startSession("TSI.sDD");
1289 enforcePermission(MODIFY_PHONE_STATE);
1290 enforcePermission(WRITE_SECURE_SETTINGS);
1291 synchronized (mLock) {
1292 long token = Binder.clearCallingIdentity();
1293 try {
Hall Liu7c928322016-12-06 18:15:39 -08001294 final boolean result = mDefaultDialerCache.setDefaultDialer(
1295 packageName, ActivityManager.getCurrentUser());
Brad Ebinger11623a32015-11-25 13:52:02 -08001296 if (result) {
1297 final Intent intent =
1298 new Intent(TelecomManager.ACTION_DEFAULT_DIALER_CHANGED);
1299 intent.putExtra(TelecomManager.EXTRA_CHANGE_DEFAULT_DIALER_PACKAGE_NAME,
1300 packageName);
1301 mContext.sendBroadcastAsUser(intent,
1302 new UserHandle(ActivityManager.getCurrentUser()));
1303 }
1304 return result;
1305 } finally {
1306 Binder.restoreCallingIdentity(token);
Yorke Leeb3984302015-06-15 12:06:35 -07001307 }
Santos Cordonea5cb932015-05-07 16:28:38 -07001308 }
Brad Ebinger11623a32015-11-25 13:52:02 -08001309 } finally {
1310 Log.endSession();
Santos Cordonea5cb932015-05-07 16:28:38 -07001311 }
1312 }
1313
Hall Liuecd74a52016-01-12 15:26:36 -08001314 @Override
Hall Liu874c0f82016-04-29 18:13:18 -07001315 public TelecomAnalytics dumpCallAnalytics() {
Hall Liuecd74a52016-01-12 15:26:36 -08001316 try {
1317 Log.startSession("TSI.dCA");
1318 enforcePermission(DUMP);
Hall Liu874c0f82016-04-29 18:13:18 -07001319 return Analytics.dumpToParcelableAnalytics();
Hall Liuecd74a52016-01-12 15:26:36 -08001320 } finally {
1321 Log.endSession();
1322 }
1323 }
1324
Santos Cordonea5cb932015-05-07 16:28:38 -07001325 /**
Tyler Gunn47689862014-12-17 17:10:28 -08001326 * Dumps the current state of the TelecomService. Used when generating problem reports.
1327 *
1328 * @param fd The file descriptor.
1329 * @param writer The print writer to dump the state to.
1330 * @param args Optional dump arguments.
1331 */
1332 @Override
1333 protected void dump(FileDescriptor fd, final PrintWriter writer, String[] args) {
1334 if (mContext.checkCallingOrSelfPermission(
1335 android.Manifest.permission.DUMP)
1336 != PackageManager.PERMISSION_GRANTED) {
1337 writer.println("Permission Denial: can't dump TelecomService " +
1338 "from from pid=" + Binder.getCallingPid() + ", uid=" +
1339 Binder.getCallingUid());
1340 return;
1341 }
1342
Hall Liu5bbbcf72016-08-08 17:23:20 -07001343 if (args.length > 0 && Analytics.ANALYTICS_DUMPSYS_ARG.equals(args[0])) {
1344 Analytics.dumpToEncodedProto(writer, args);
1345 return;
1346 }
Tyler Gunn897e8512017-05-18 15:46:51 -07001347 boolean isTimeLineView = (args.length > 0 && TIME_LINE_ARG.equalsIgnoreCase(args[0]));
Hall Liu5bbbcf72016-08-08 17:23:20 -07001348
Tyler Gunn47689862014-12-17 17:10:28 -08001349 final IndentingPrintWriter pw = new IndentingPrintWriter(writer, " ");
Ihab Awad8de76912015-02-17 12:25:52 -08001350 if (mCallsManager != null) {
Ihab Awad78a5e6b2015-02-06 10:13:05 -08001351 pw.println("CallsManager: ");
Tyler Gunn47689862014-12-17 17:10:28 -08001352 pw.increaseIndent();
Ihab Awad8de76912015-02-17 12:25:52 -08001353 mCallsManager.dump(pw);
Tyler Gunn47689862014-12-17 17:10:28 -08001354 pw.decreaseIndent();
1355
Ihab Awad78a5e6b2015-02-06 10:13:05 -08001356 pw.println("PhoneAccountRegistrar: ");
Tyler Gunn47689862014-12-17 17:10:28 -08001357 pw.increaseIndent();
Ihab Awad8d5d9dd2015-03-12 11:11:06 -07001358 mPhoneAccountRegistrar.dump(pw);
Tyler Gunn47689862014-12-17 17:10:28 -08001359 pw.decreaseIndent();
Hall Liu32587202015-11-18 11:10:08 -08001360
1361 pw.println("Analytics:");
1362 pw.increaseIndent();
1363 Analytics.dump(pw);
1364 pw.decreaseIndent();
Tyler Gunn47689862014-12-17 17:10:28 -08001365 }
Tyler Gunn897e8512017-05-18 15:46:51 -07001366 if (isTimeLineView) {
1367 Log.dumpEventsTimeline(pw);
1368 } else {
1369 Log.dumpEvents(pw);
1370 }
Tyler Gunn47689862014-12-17 17:10:28 -08001371 }
Abhijith Shastry7a846f52016-02-01 16:49:27 -08001372
Mohamedc9261852016-02-05 14:10:17 -08001373 /**
Abhijith Shastryb1308ec2016-02-29 16:26:09 -08001374 * @see android.telecom.TelecomManager#createManageBlockedNumbersIntent
1375 */
Abhijith Shastryebe7bbe2016-02-29 11:16:30 -08001376 @Override
1377 public Intent createManageBlockedNumbersIntent() {
Abhijith Shastryb1308ec2016-02-29 16:26:09 -08001378 return BlockedNumbersActivity.getIntentForStartingActivity();
Abhijith Shastryebe7bbe2016-02-29 11:16:30 -08001379 }
Tyler Gunnacb3bc82017-01-09 09:43:56 -08001380
1381 /**
1382 * @see android.telecom.TelecomManager#isIncomingCallPermitted(PhoneAccountHandle)
1383 */
1384 @Override
1385 public boolean isIncomingCallPermitted(PhoneAccountHandle phoneAccountHandle) {
1386 try {
1387 Log.startSession("TSI.iICP");
1388 enforcePermission(android.Manifest.permission.MANAGE_OWN_CALLS);
1389 synchronized (mLock) {
1390 long token = Binder.clearCallingIdentity();
1391 try {
Tyler Gunna90ba732017-01-26 07:24:08 -08001392 return mCallsManager.isIncomingCallPermitted(phoneAccountHandle);
Tyler Gunnacb3bc82017-01-09 09:43:56 -08001393 } finally {
1394 Binder.restoreCallingIdentity(token);
1395 }
1396 }
1397 } finally {
1398 Log.endSession();
1399 }
Tyler Gunnacb3bc82017-01-09 09:43:56 -08001400 }
1401
1402 /**
1403 * @see android.telecom.TelecomManager#isOutgoingCallPermitted(PhoneAccountHandle)
1404 */
1405 @Override
1406 public boolean isOutgoingCallPermitted(PhoneAccountHandle phoneAccountHandle) {
1407 try {
1408 Log.startSession("TSI.iOCP");
1409 enforcePermission(android.Manifest.permission.MANAGE_OWN_CALLS);
1410 synchronized (mLock) {
1411 long token = Binder.clearCallingIdentity();
1412 try {
Tyler Gunna90ba732017-01-26 07:24:08 -08001413 return mCallsManager.isOutgoingCallPermitted(phoneAccountHandle);
Tyler Gunnacb3bc82017-01-09 09:43:56 -08001414 } finally {
1415 Binder.restoreCallingIdentity(token);
1416 }
1417 }
1418 } finally {
1419 Log.endSession();
1420 }
Tyler Gunnacb3bc82017-01-09 09:43:56 -08001421 }
Tyler Gunn9e806ee2017-02-06 20:49:24 -08001422
1423 /**
1424 * Blocks until all Telecom handlers have completed their current work.
1425 *
1426 * See {@link com.android.commands.telecom.Telecom}.
1427 */
1428 @Override
1429 public void waitOnHandlers() {
1430 try {
1431 Log.startSession("TSI.wOH");
1432 enforceModifyPermission();
1433 synchronized (mLock) {
1434 long token = Binder.clearCallingIdentity();
1435 try {
1436 Log.i(this, "waitOnHandlers");
1437 mCallsManager.waitOnHandlers();
1438 } finally {
1439 Binder.restoreCallingIdentity(token);
1440 }
1441 }
1442 } finally {
1443 Log.endSession();
1444 }
1445 }
Ihab Awad8d5d9dd2015-03-12 11:11:06 -07001446 };
1447
Eugene Suslaccba7202017-02-10 10:56:53 -08001448 /**
1449 * @return whether to return early without doing the action/throwing
1450 * @throws SecurityException same as {@link Context#enforceCallingOrSelfPermission}
1451 */
1452 private boolean enforceAnswerCallPermission(String packageName, int uid) {
1453 try {
1454 enforceModifyPermission();
1455 } catch (SecurityException e) {
1456 final String permission = Manifest.permission.ANSWER_PHONE_CALLS;
1457 enforcePermission(permission);
1458
1459 final int opCode = AppOpsManager.permissionToOpCode(permission);
1460 if (opCode != AppOpsManager.OP_NONE
1461 && mAppOpsManager.checkOp(opCode, uid, packageName)
1462 != AppOpsManager.MODE_ALLOWED) {
1463 return false;
1464 }
1465 }
1466 return true;
1467 }
1468
Tyler Gunn37a4dca2018-01-18 15:00:41 -08001469 /**
1470 * @return {@code true} if the app has the handover permission and has received runtime
1471 * permission to perform that operation, {@code false}.
1472 * @throws SecurityException same as {@link Context#enforceCallingOrSelfPermission}
1473 */
1474 private boolean enforceAcceptHandoverPermission(String packageName, int uid) {
1475 mContext.enforceCallingOrSelfPermission(Manifest.permission.ACCEPT_HANDOVER,
1476 "App requires ACCEPT_HANDOVER permission to accept handovers.");
1477
1478 final int opCode = AppOpsManager.permissionToOpCode(Manifest.permission.ACCEPT_HANDOVER);
1479 if (opCode != AppOpsManager.OP_ACCEPT_HANDOVER || (
1480 mAppOpsManager.checkOp(opCode, uid, packageName)
1481 != AppOpsManager.MODE_ALLOWED)) {
1482 return false;
1483 }
1484 return true;
1485 }
1486
Ihab Awad8d5d9dd2015-03-12 11:11:06 -07001487 private Context mContext;
1488 private AppOpsManager mAppOpsManager;
Ihab Awad8d5d9dd2015-03-12 11:11:06 -07001489 private PackageManager mPackageManager;
1490 private CallsManager mCallsManager;
1491 private final PhoneAccountRegistrar mPhoneAccountRegistrar;
Hall Liuecda5542015-12-04 11:31:31 -08001492 private final CallIntentProcessor.Adapter mCallIntentProcessorAdapter;
1493 private final UserCallIntentProcessorFactory mUserCallIntentProcessorFactory;
Hall Liu7c928322016-12-06 18:15:39 -08001494 private final DefaultDialerCache mDefaultDialerCache;
Hall Liu0a6dd302015-12-16 15:06:49 -08001495 private final SubscriptionManagerAdapter mSubscriptionManagerAdapter;
Ihab Awad8d5d9dd2015-03-12 11:11:06 -07001496 private final TelecomSystem.SyncRoot mLock;
1497
1498 public TelecomServiceImpl(
1499 Context context,
1500 CallsManager callsManager,
1501 PhoneAccountRegistrar phoneAccountRegistrar,
Hall Liuecda5542015-12-04 11:31:31 -08001502 CallIntentProcessor.Adapter callIntentProcessorAdapter,
1503 UserCallIntentProcessorFactory userCallIntentProcessorFactory,
Hall Liu7c928322016-12-06 18:15:39 -08001504 DefaultDialerCache defaultDialerCache,
Hall Liu0a6dd302015-12-16 15:06:49 -08001505 SubscriptionManagerAdapter subscriptionManagerAdapter,
Ihab Awad8d5d9dd2015-03-12 11:11:06 -07001506 TelecomSystem.SyncRoot lock) {
1507 mContext = context;
1508 mAppOpsManager = (AppOpsManager) mContext.getSystemService(Context.APP_OPS_SERVICE);
1509
Ihab Awad8d5d9dd2015-03-12 11:11:06 -07001510 mPackageManager = mContext.getPackageManager();
1511
1512 mCallsManager = callsManager;
1513 mLock = lock;
1514 mPhoneAccountRegistrar = phoneAccountRegistrar;
Hall Liuecda5542015-12-04 11:31:31 -08001515 mUserCallIntentProcessorFactory = userCallIntentProcessorFactory;
Hall Liu7c928322016-12-06 18:15:39 -08001516 mDefaultDialerCache = defaultDialerCache;
Hall Liuecda5542015-12-04 11:31:31 -08001517 mCallIntentProcessorAdapter = callIntentProcessorAdapter;
Hall Liu0a6dd302015-12-16 15:06:49 -08001518 mSubscriptionManagerAdapter = subscriptionManagerAdapter;
Ihab Awad8d5d9dd2015-03-12 11:11:06 -07001519 }
1520
Ihab Awadaa383cc2015-03-22 22:12:28 -07001521 public ITelecomService.Stub getBinder() {
Ihab Awad8d5d9dd2015-03-12 11:11:06 -07001522 return mBinderImpl;
Santos Cordonf987d1a2014-12-02 03:37:03 -08001523 }
1524
1525 //
1526 // Supporting methods for the ITelecomService interface implementation.
1527 //
1528
Tony Mak240656f2015-12-04 11:36:22 +00001529 private boolean isPhoneAccountHandleVisibleToCallingUser(
1530 PhoneAccountHandle phoneAccountUserHandle, UserHandle callingUser) {
1531 return mPhoneAccountRegistrar.getPhoneAccount(phoneAccountUserHandle, callingUser) != null;
Santos Cordonf987d1a2014-12-02 03:37:03 -08001532 }
1533
1534 private boolean isCallerSystemApp() {
1535 int uid = Binder.getCallingUid();
1536 String[] packages = mPackageManager.getPackagesForUid(uid);
1537 for (String packageName : packages) {
1538 if (isPackageSystemApp(packageName)) {
1539 return true;
1540 }
1541 }
1542 return false;
1543 }
1544
1545 private boolean isPackageSystemApp(String packageName) {
1546 try {
1547 ApplicationInfo applicationInfo = mPackageManager.getApplicationInfo(packageName,
1548 PackageManager.GET_META_DATA);
1549 if ((applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0) {
1550 return true;
1551 }
1552 } catch (PackageManager.NameNotFoundException e) {
1553 }
1554 return false;
1555 }
1556
Tyler Gunn42ef8082015-11-24 15:34:34 -08001557 private void acceptRingingCallInternal(int videoState) {
Ihab Awad8de76912015-02-17 12:25:52 -08001558 Call call = mCallsManager.getFirstCallWithState(CallState.RINGING);
Santos Cordonf987d1a2014-12-02 03:37:03 -08001559 if (call != null) {
Tyler Gunn42ef8082015-11-24 15:34:34 -08001560 if (videoState == DEFAULT_VIDEO_STATE || !isValidAcceptVideoState(videoState)) {
1561 videoState = call.getVideoState();
1562 }
1563 call.answer(videoState);
Santos Cordonf987d1a2014-12-02 03:37:03 -08001564 }
1565 }
1566
Tyler Gunn587fc272018-02-07 16:07:29 -08001567 private boolean endCallInternal(String callingPackage) {
Santos Cordonf987d1a2014-12-02 03:37:03 -08001568 // Always operate on the foreground call if one exists, otherwise get the first call in
1569 // priority order by call-state.
Ihab Awad8de76912015-02-17 12:25:52 -08001570 Call call = mCallsManager.getForegroundCall();
Santos Cordonf987d1a2014-12-02 03:37:03 -08001571 if (call == null) {
Ihab Awad8de76912015-02-17 12:25:52 -08001572 call = mCallsManager.getFirstCallWithState(
Santos Cordonf987d1a2014-12-02 03:37:03 -08001573 CallState.ACTIVE,
1574 CallState.DIALING,
Tyler Gunn1e37be52016-07-11 08:54:23 -07001575 CallState.PULLING,
Santos Cordonf987d1a2014-12-02 03:37:03 -08001576 CallState.RINGING,
1577 CallState.ON_HOLD);
1578 }
1579
1580 if (call != null) {
1581 if (call.getState() == CallState.RINGING) {
Tyler Gunn587fc272018-02-07 16:07:29 -08001582 call.reject(false /* rejectWithMessage */, null, callingPackage);
Santos Cordonf987d1a2014-12-02 03:37:03 -08001583 } else {
Tyler Gunn587fc272018-02-07 16:07:29 -08001584 call.disconnect(0 /* disconnectionTimeout */, callingPackage);
Santos Cordonf987d1a2014-12-02 03:37:03 -08001585 }
1586 return true;
1587 }
1588
1589 return false;
1590 }
1591
Brad Ebinger62da8e12016-01-28 19:16:08 -08001592 // Enforce that the PhoneAccountHandle being passed in is both registered to the current user
1593 // and enabled.
Tony Mak5851fa02016-02-23 19:41:52 +00001594 private void enforcePhoneAccountIsRegisteredEnabled(PhoneAccountHandle phoneAccountHandle,
1595 UserHandle callingUserHandle) {
1596 PhoneAccount phoneAccount = mPhoneAccountRegistrar.getPhoneAccount(phoneAccountHandle,
1597 callingUserHandle);
Brad Ebinger62da8e12016-01-28 19:16:08 -08001598 if(phoneAccount == null) {
1599 EventLog.writeEvent(0x534e4554, "26864502", Binder.getCallingUid(), "R");
1600 throw new SecurityException("This PhoneAccountHandle is not registered for this user!");
1601 }
1602 if(!phoneAccount.isEnabled()) {
1603 EventLog.writeEvent(0x534e4554, "26864502", Binder.getCallingUid(), "E");
1604 throw new SecurityException("This PhoneAccountHandle is not enabled for this user!");
1605 }
1606 }
1607
Santos Cordonf987d1a2014-12-02 03:37:03 -08001608 private void enforcePhoneAccountModificationForPackage(String packageName) {
1609 // TODO: Use a new telecomm permission for this instead of reusing modify.
1610
Yorke Leecb0bd8a2015-05-18 11:57:14 -07001611 int result = mContext.checkCallingOrSelfPermission(MODIFY_PHONE_STATE);
Santos Cordonf987d1a2014-12-02 03:37:03 -08001612
1613 // Callers with MODIFY_PHONE_STATE can use the PhoneAccount mechanism to implement
1614 // built-in behavior even when PhoneAccounts are not exposed as a third-part API. They
1615 // may also modify PhoneAccounts on behalf of any 'packageName'.
1616
1617 if (result != PackageManager.PERMISSION_GRANTED) {
1618 // Other callers are only allowed to modify PhoneAccounts if the relevant system
1619 // feature is enabled ...
1620 enforceConnectionServiceFeature();
1621 // ... and the PhoneAccounts they refer to are for their own package.
1622 enforceCallingPackage(packageName);
1623 }
1624 }
1625
Yorke Leecb0bd8a2015-05-18 11:57:14 -07001626 private void enforcePermissionOrPrivilegedDialer(String permission, String packageName) {
Yorke Lee53101962015-04-29 16:25:29 -07001627 if (!isPrivilegedDialerCalling(packageName)) {
1628 try {
Yorke Leecb0bd8a2015-05-18 11:57:14 -07001629 enforcePermission(permission);
Yorke Lee53101962015-04-29 16:25:29 -07001630 } catch (SecurityException e) {
Yorke Leecb0bd8a2015-05-18 11:57:14 -07001631 Log.e(this, e, "Caller must be the default or system dialer, or have the permission"
1632 + " %s to perform this operation.", permission);
Yorke Lee53101962015-04-29 16:25:29 -07001633 throw e;
1634 }
Santos Cordonf987d1a2014-12-02 03:37:03 -08001635 }
1636 }
1637
1638 private void enforceCallingPackage(String packageName) {
1639 mAppOpsManager.checkPackage(Binder.getCallingUid(), packageName);
1640 }
1641
1642 private void enforceConnectionServiceFeature() {
1643 enforceFeature(PackageManager.FEATURE_CONNECTION_SERVICE);
1644 }
1645
Santos Cordonf987d1a2014-12-02 03:37:03 -08001646 private void enforceRegisterSimSubscriptionPermission() {
Yorke Leecb0bd8a2015-05-18 11:57:14 -07001647 enforcePermission(REGISTER_SIM_SUBSCRIPTION);
Santos Cordonf987d1a2014-12-02 03:37:03 -08001648 }
1649
Santos Cordonf987d1a2014-12-02 03:37:03 -08001650 private void enforceModifyPermission() {
Yorke Leecb0bd8a2015-05-18 11:57:14 -07001651 enforcePermission(MODIFY_PHONE_STATE);
Santos Cordonf987d1a2014-12-02 03:37:03 -08001652 }
1653
Tyler Gunn322480c2017-07-17 15:34:02 -07001654 private void enforceModifyPermission(String message) {
1655 mContext.enforceCallingOrSelfPermission(MODIFY_PHONE_STATE, message);
1656 }
1657
Santos Cordonf987d1a2014-12-02 03:37:03 -08001658 private void enforcePermission(String permission) {
1659 mContext.enforceCallingOrSelfPermission(permission, null);
1660 }
1661
Tyler Gunnacb3bc82017-01-09 09:43:56 -08001662 private void enforceRegisterSelfManaged() {
1663 mContext.enforceCallingPermission(android.Manifest.permission.MANAGE_OWN_CALLS, null);
1664 }
1665
Santos Cordonf987d1a2014-12-02 03:37:03 -08001666 private void enforceRegisterMultiUser() {
1667 if (!isCallerSystemApp()) {
1668 throw new SecurityException("CAPABILITY_MULTI_USER is only available to system apps.");
1669 }
1670 }
1671
1672 private void enforceUserHandleMatchesCaller(PhoneAccountHandle accountHandle) {
1673 if (!Binder.getCallingUserHandle().equals(accountHandle.getUserHandle())) {
1674 throw new SecurityException("Calling UserHandle does not match PhoneAccountHandle's");
1675 }
1676 }
1677
Tony Mak240656f2015-12-04 11:36:22 +00001678 private void enforceCrossUserPermission(int callingUid) {
1679 if (callingUid != Process.SYSTEM_UID && callingUid != 0) {
1680 mContext.enforceCallingOrSelfPermission(
1681 android.Manifest.permission.INTERACT_ACROSS_USERS_FULL, "Must be system or have"
1682 + " INTERACT_ACROSS_USERS_FULL permission");
1683 }
1684 }
1685
Santos Cordonf987d1a2014-12-02 03:37:03 -08001686 private void enforceFeature(String feature) {
1687 PackageManager pm = mContext.getPackageManager();
1688 if (!pm.hasSystemFeature(feature)) {
1689 throw new UnsupportedOperationException(
1690 "System does not support feature " + feature);
1691 }
1692 }
1693
Svet Ganov38f1a4d2015-04-17 15:28:03 -07001694 private boolean canReadPhoneState(String callingPackage, String message) {
Yorke Lee57138a62015-05-18 18:18:08 -07001695 // The system/default dialer can always read phone state - so that emergency calls will
1696 // still work.
1697 if (isPrivilegedDialerCalling(callingPackage)) {
1698 return true;
1699 }
1700
Amit Mahajan3c296932015-07-14 10:23:15 -07001701 try {
Amit Mahajan86b8e332015-07-30 16:02:52 -07001702 mContext.enforceCallingOrSelfPermission(READ_PRIVILEGED_PHONE_STATE, message);
1703 // SKIP checking run-time OP_READ_PHONE_STATE since caller or self has PRIVILEGED
1704 // permission
Amit Mahajan3c296932015-07-14 10:23:15 -07001705 return true;
1706 } catch (SecurityException e) {
1707 // Accessing phone state is gated by a special permission.
1708 mContext.enforceCallingOrSelfPermission(READ_PHONE_STATE, message);
Svet Ganov09611182015-04-16 12:29:01 -07001709
Amit Mahajan3c296932015-07-14 10:23:15 -07001710 // Some apps that have the permission can be restricted via app ops.
1711 return mAppOpsManager.noteOp(AppOpsManager.OP_READ_PHONE_STATE,
1712 Binder.getCallingUid(), callingPackage) == AppOpsManager.MODE_ALLOWED;
1713 }
Svet Ganov09611182015-04-16 12:29:01 -07001714 }
1715
Tyler Gunna90ba732017-01-26 07:24:08 -08001716 private boolean isSelfManagedConnectionService(PhoneAccountHandle phoneAccountHandle) {
1717 if (phoneAccountHandle != null) {
1718 PhoneAccount phoneAccount = mPhoneAccountRegistrar.getPhoneAccountUnchecked(
1719 phoneAccountHandle);
Tyler Gunn9e806ee2017-02-06 20:49:24 -08001720 return phoneAccount != null && phoneAccount.isSelfManaged();
Tyler Gunna90ba732017-01-26 07:24:08 -08001721 }
1722 return false;
1723 }
1724
Yorke Leea3a3adc2015-04-23 12:49:01 -07001725 private boolean canCallPhone(String callingPackage, String message) {
Yorke Lee57138a62015-05-18 18:18:08 -07001726 // The system/default dialer can always read phone state - so that emergency calls will
1727 // still work.
1728 if (isPrivilegedDialerCalling(callingPackage)) {
1729 return true;
1730 }
1731
Yorke Leea3a3adc2015-04-23 12:49:01 -07001732 // Accessing phone state is gated by a special permission.
Yorke Leecb0bd8a2015-05-18 11:57:14 -07001733 mContext.enforceCallingOrSelfPermission(CALL_PHONE, message);
Yorke Leea3a3adc2015-04-23 12:49:01 -07001734
1735 // Some apps that have the permission can be restricted via app ops.
1736 return mAppOpsManager.noteOp(AppOpsManager.OP_CALL_PHONE,
1737 Binder.getCallingUid(), callingPackage) == AppOpsManager.MODE_ALLOWED;
1738 }
1739
Sailesh Nepal2a98c972015-03-04 15:43:15 -08001740 private boolean isCallerSimCallManager() {
Yorke Lee9427c0f2015-06-27 11:01:58 -07001741 long token = Binder.clearCallingIdentity();
Tony Mak240656f2015-12-04 11:36:22 +00001742 PhoneAccountHandle accountHandle = null;
Yorke Lee9427c0f2015-06-27 11:01:58 -07001743 try {
Tony Mak240656f2015-12-04 11:36:22 +00001744 accountHandle = mPhoneAccountRegistrar.getSimCallManagerOfCurrentUser();
Yorke Lee9427c0f2015-06-27 11:01:58 -07001745 } finally {
1746 Binder.restoreCallingIdentity(token);
1747 }
1748
Sailesh Nepal2a98c972015-03-04 15:43:15 -08001749 if (accountHandle != null) {
1750 try {
1751 mAppOpsManager.checkPackage(
1752 Binder.getCallingUid(), accountHandle.getComponentName().getPackageName());
1753 return true;
1754 } catch (SecurityException e) {
1755 }
1756 }
1757 return false;
1758 }
1759
Yorke Lee53101962015-04-29 16:25:29 -07001760 private boolean isPrivilegedDialerCalling(String callingPackage) {
1761 mAppOpsManager.checkPackage(Binder.getCallingUid(), callingPackage);
Hall Liu7c928322016-12-06 18:15:39 -08001762 return mDefaultDialerCache.isDefaultOrSystemDialer(
1763 callingPackage, Binder.getCallingUserHandle().getIdentifier());
Santos Cordonf987d1a2014-12-02 03:37:03 -08001764 }
1765
1766 private TelephonyManager getTelephonyManager() {
Hall Liuecda5542015-12-04 11:31:31 -08001767 return (TelephonyManager) mContext.getSystemService(Context.TELEPHONY_SERVICE);
Santos Cordonf987d1a2014-12-02 03:37:03 -08001768 }
Tyler Gunn42ef8082015-11-24 15:34:34 -08001769
1770 /**
1771 * Determines if a video state is valid for accepting an incoming call.
1772 * For the purpose of accepting a call, states {@link VideoProfile#STATE_AUDIO_ONLY}, and
1773 * any combination of {@link VideoProfile#STATE_RX_ENABLED} and
1774 * {@link VideoProfile#STATE_TX_ENABLED} are considered valid.
1775 *
1776 * @param videoState The video state.
1777 * @return {@code true} if the video state is valid, {@code false} otherwise.
1778 */
1779 private boolean isValidAcceptVideoState(int videoState) {
1780 // Given a video state input, turn off TX and RX so that we can determine if those were the
1781 // only bits set.
1782 int remainingState = videoState & ~VideoProfile.STATE_TX_ENABLED;
1783 remainingState = remainingState & ~VideoProfile.STATE_RX_ENABLED;
1784
1785 // If only TX or RX were set (or neither), the video state is valid.
1786 return remainingState == 0;
1787 }
Santos Cordonf987d1a2014-12-02 03:37:03 -08001788}