blob: 274b60e1c505b63d8d3659b52c46fe727a28dc19 [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;
20import static android.Manifest.permission.MODIFY_PHONE_STATE;
21import static android.Manifest.permission.READ_PHONE_STATE;
22import static android.Manifest.permission.REGISTER_CALL_PROVIDER;
23import static android.Manifest.permission.REGISTER_CONNECTION_MANAGER;
24import static android.Manifest.permission.REGISTER_SIM_SUBSCRIPTION;
25
Santos Cordonf987d1a2014-12-02 03:37:03 -080026import android.app.AppOpsManager;
Santos Cordonf987d1a2014-12-02 03:37:03 -080027import android.content.ComponentName;
28import android.content.Context;
29import android.content.Intent;
30import android.content.pm.ApplicationInfo;
31import android.content.pm.PackageManager;
32import android.content.res.Resources;
33import android.net.Uri;
34import android.os.Binder;
35import android.os.Bundle;
Santos Cordonf987d1a2014-12-02 03:37:03 -080036import android.os.IBinder;
Santos Cordonf987d1a2014-12-02 03:37:03 -080037import android.os.UserHandle;
38import android.os.UserManager;
Yorke Lee5b3fc0a2015-04-23 17:42:57 -070039import android.telecom.DefaultDialerManager;
Santos Cordonf987d1a2014-12-02 03:37:03 -080040import android.telecom.PhoneAccount;
41import android.telecom.PhoneAccountHandle;
42import android.telecom.TelecomManager;
43import android.telephony.SubscriptionManager;
44import android.telephony.TelephonyManager;
45import android.text.TextUtils;
46
47// TODO: Needed for move to system service: import com.android.internal.R;
48import com.android.internal.telecom.ITelecomService;
49import com.android.internal.util.IndentingPrintWriter;
Yorke Leea3a3adc2015-04-23 12:49:01 -070050import com.android.server.telecom.components.UserCallIntentProcessor;
Santos Cordonf987d1a2014-12-02 03:37:03 -080051
52import java.io.FileDescriptor;
53import java.io.PrintWriter;
54import java.util.ArrayList;
Svet Ganov09611182015-04-16 12:29:01 -070055import java.util.Collections;
Santos Cordonf987d1a2014-12-02 03:37:03 -080056import java.util.List;
57
58/**
59 * Implementation of the ITelecom interface.
60 */
Ihab Awad78a5e6b2015-02-06 10:13:05 -080061public class TelecomServiceImpl {
Santos Cordon73853962015-02-27 15:13:35 -080062 private static final String PERMISSION_PROCESS_PHONE_ACCOUNT_REGISTRATION =
63 "android.permission.PROCESS_PHONE_ACCOUNT_REGISTRATION";
64
Ihab Awad8d5d9dd2015-03-12 11:11:06 -070065 private final ITelecomService.Stub mBinderImpl = new ITelecomService.Stub() {
Santos Cordonf987d1a2014-12-02 03:37:03 -080066 @Override
Svet Ganov09611182015-04-16 12:29:01 -070067 public PhoneAccountHandle getDefaultOutgoingPhoneAccount(String uriScheme,
68 String callingPackage) {
Ihab Awad8d5d9dd2015-03-12 11:11:06 -070069 synchronized (mLock) {
Svet Ganov38f1a4d2015-04-17 15:28:03 -070070 if (!canReadPhoneState(callingPackage, "getDefaultOutgoingPhoneAccount")) {
Svet Ganov09611182015-04-16 12:29:01 -070071 return null;
72 }
73
Ihab Awad8d5d9dd2015-03-12 11:11:06 -070074 long token = Binder.clearCallingIdentity();
75 try {
76 PhoneAccountHandle defaultOutgoingPhoneAccount =
Santos Cordon6a212642015-05-08 16:35:23 -070077 mPhoneAccountRegistrar.getOutgoingPhoneAccountForScheme(uriScheme);
Ihab Awad8d5d9dd2015-03-12 11:11:06 -070078 // Make sure that the calling user can see this phone account.
Santos Cordonebf2d0f2015-05-15 10:28:29 -070079 // TODO: Does this isVisible check actually work considering we are clearing
80 // the calling identity?
Ihab Awad8d5d9dd2015-03-12 11:11:06 -070081 if (defaultOutgoingPhoneAccount != null
82 && !isVisibleToCaller(defaultOutgoingPhoneAccount)) {
83 Log.w(this, "No account found for the calling user");
84 return null;
85 }
86 return defaultOutgoingPhoneAccount;
87 } catch (Exception e) {
88 Log.e(this, e, "getDefaultOutgoingPhoneAccount");
89 throw e;
90 } finally {
91 Binder.restoreCallingIdentity(token);
Santos Cordonf987d1a2014-12-02 03:37:03 -080092 }
Santos Cordonf987d1a2014-12-02 03:37:03 -080093 }
94 }
95
96 @Override
97 public PhoneAccountHandle getUserSelectedOutgoingPhoneAccount() {
Ihab Awad8d5d9dd2015-03-12 11:11:06 -070098 synchronized (mLock) {
99 try {
100 PhoneAccountHandle userSelectedOutgoingPhoneAccount =
101 mPhoneAccountRegistrar.getUserSelectedOutgoingPhoneAccount();
102 // Make sure that the calling user can see this phone account.
103 if (!isVisibleToCaller(userSelectedOutgoingPhoneAccount)) {
104 Log.w(this, "No account found for the calling user");
105 return null;
106 }
107 return userSelectedOutgoingPhoneAccount;
108 } catch (Exception e) {
109 Log.e(this, e, "getUserSelectedOutgoingPhoneAccount");
110 throw e;
Santos Cordonf987d1a2014-12-02 03:37:03 -0800111 }
Santos Cordonf987d1a2014-12-02 03:37:03 -0800112 }
113 }
114
115 @Override
116 public void setUserSelectedOutgoingPhoneAccount(PhoneAccountHandle accountHandle) {
Ihab Awad8d5d9dd2015-03-12 11:11:06 -0700117 synchronized (mLock) {
118 enforceModifyPermission();
Santos Cordonebf2d0f2015-05-15 10:28:29 -0700119
120 long token = Binder.clearCallingIdentity();
Ihab Awad8d5d9dd2015-03-12 11:11:06 -0700121 try {
122 mPhoneAccountRegistrar.setUserSelectedOutgoingPhoneAccount(accountHandle);
123 } catch (Exception e) {
124 Log.e(this, e, "setUserSelectedOutgoingPhoneAccount");
125 throw e;
Santos Cordonebf2d0f2015-05-15 10:28:29 -0700126 } finally {
127 Binder.restoreCallingIdentity(token);
Ihab Awad8d5d9dd2015-03-12 11:11:06 -0700128 }
Santos Cordonf987d1a2014-12-02 03:37:03 -0800129 }
130 }
131
132 @Override
Svet Ganov09611182015-04-16 12:29:01 -0700133 public List<PhoneAccountHandle> getCallCapablePhoneAccounts(String callingPackage) {
Svet Ganov38f1a4d2015-04-17 15:28:03 -0700134 if (!canReadPhoneState(callingPackage, "getDefaultOutgoingPhoneAccount")) {
Svet Ganov09611182015-04-16 12:29:01 -0700135 return Collections.emptyList();
136 }
137
Ihab Awad8d5d9dd2015-03-12 11:11:06 -0700138 synchronized (mLock) {
Ihab Awad8d5d9dd2015-03-12 11:11:06 -0700139 long token = Binder.clearCallingIdentity();
140 try {
Santos Cordonebf2d0f2015-05-15 10:28:29 -0700141 // TODO: Does this isVisible check actually work considering we are clearing
142 // the calling identity?
Ihab Awad8d5d9dd2015-03-12 11:11:06 -0700143 return filterForAccountsVisibleToCaller(
Santos Cordon6a212642015-05-08 16:35:23 -0700144 mPhoneAccountRegistrar.getCallCapablePhoneAccounts(null));
Ihab Awad8d5d9dd2015-03-12 11:11:06 -0700145 } catch (Exception e) {
146 Log.e(this, e, "getCallCapablePhoneAccounts");
147 throw e;
148 } finally {
149 Binder.restoreCallingIdentity(token);
150 }
Santos Cordonf987d1a2014-12-02 03:37:03 -0800151 }
152 }
153
154 @Override
Svet Ganov09611182015-04-16 12:29:01 -0700155 public List<PhoneAccountHandle> getPhoneAccountsSupportingScheme(String uriScheme,
156 String callingPackage) {
Ihab Awad8d5d9dd2015-03-12 11:11:06 -0700157 synchronized (mLock) {
Svet Ganov38f1a4d2015-04-17 15:28:03 -0700158 if (!canReadPhoneState(callingPackage, "getPhoneAccountsSupportingScheme")) {
Svet Ganov09611182015-04-16 12:29:01 -0700159 return Collections.emptyList();
160 }
161
Ihab Awad8d5d9dd2015-03-12 11:11:06 -0700162 long token = Binder.clearCallingIdentity();
163 try {
Santos Cordonebf2d0f2015-05-15 10:28:29 -0700164 // TODO: Does this isVisible check actually work considering we are clearing
165 // the calling identity?
Ihab Awad8d5d9dd2015-03-12 11:11:06 -0700166 return filterForAccountsVisibleToCaller(
167 mPhoneAccountRegistrar.getCallCapablePhoneAccounts(uriScheme));
168 } catch (Exception e) {
169 Log.e(this, e, "getPhoneAccountsSupportingScheme %s", uriScheme);
170 throw e;
171 } finally {
172 Binder.restoreCallingIdentity(token);
173 }
Santos Cordonf987d1a2014-12-02 03:37:03 -0800174 }
175 }
176
177 @Override
178 public List<PhoneAccountHandle> getPhoneAccountsForPackage(String packageName) {
Ihab Awad8d5d9dd2015-03-12 11:11:06 -0700179 synchronized (mLock) {
180 try {
181 return filterForAccountsVisibleToCaller(
182 mPhoneAccountRegistrar.getPhoneAccountsForPackage(packageName));
183 } catch (Exception e) {
184 Log.e(this, e, "getPhoneAccountsForPackage %s", packageName);
185 throw e;
186 }
Santos Cordonf987d1a2014-12-02 03:37:03 -0800187 }
188 }
189
190 @Override
191 public PhoneAccount getPhoneAccount(PhoneAccountHandle accountHandle) {
Ihab Awad8d5d9dd2015-03-12 11:11:06 -0700192 synchronized (mLock) {
193 try {
194 if (!isVisibleToCaller(accountHandle)) {
195 Log.w(this, "%s is not visible for the calling user", accountHandle);
196 return null;
197 }
Santos Cordon6a212642015-05-08 16:35:23 -0700198 // TODO: Do we really want to return for *any* user?
199 return mPhoneAccountRegistrar.getPhoneAccount(accountHandle);
Ihab Awad8d5d9dd2015-03-12 11:11:06 -0700200 } catch (Exception e) {
201 Log.e(this, e, "getPhoneAccount %s", accountHandle);
202 throw e;
Santos Cordonf987d1a2014-12-02 03:37:03 -0800203 }
Santos Cordonf987d1a2014-12-02 03:37:03 -0800204 }
205 }
206
207 @Override
208 public int getAllPhoneAccountsCount() {
Ihab Awad8d5d9dd2015-03-12 11:11:06 -0700209 synchronized (mLock) {
210 try {
211 // This list is pre-filtered for the calling user.
212 return getAllPhoneAccounts().size();
213 } catch (Exception e) {
214 Log.e(this, e, "getAllPhoneAccountsCount");
215 throw e;
216 }
Santos Cordonf987d1a2014-12-02 03:37:03 -0800217 }
218 }
219
220 @Override
221 public List<PhoneAccount> getAllPhoneAccounts() {
Ihab Awad8d5d9dd2015-03-12 11:11:06 -0700222 synchronized (mLock) {
223 try {
224 List<PhoneAccount> allPhoneAccounts = mPhoneAccountRegistrar
225 .getAllPhoneAccounts();
226 List<PhoneAccount> profilePhoneAccounts = new ArrayList<>(
227 allPhoneAccounts.size());
228 for (PhoneAccount phoneAccount : profilePhoneAccounts) {
229 if (isVisibleToCaller(phoneAccount)) {
230 profilePhoneAccounts.add(phoneAccount);
231 }
Santos Cordonf987d1a2014-12-02 03:37:03 -0800232 }
Ihab Awad8d5d9dd2015-03-12 11:11:06 -0700233 return profilePhoneAccounts;
234 } catch (Exception e) {
235 Log.e(this, e, "getAllPhoneAccounts");
236 throw e;
Santos Cordonf987d1a2014-12-02 03:37:03 -0800237 }
Santos Cordonf987d1a2014-12-02 03:37:03 -0800238 }
239 }
240
241 @Override
242 public List<PhoneAccountHandle> getAllPhoneAccountHandles() {
Ihab Awad8d5d9dd2015-03-12 11:11:06 -0700243 synchronized (mLock) {
244 try {
245 return filterForAccountsVisibleToCaller(
246 mPhoneAccountRegistrar.getAllPhoneAccountHandles());
247 } catch (Exception e) {
248 Log.e(this, e, "getAllPhoneAccounts");
249 throw e;
250 }
Santos Cordonf987d1a2014-12-02 03:37:03 -0800251 }
252 }
253
254 @Override
255 public PhoneAccountHandle getSimCallManager() {
Ihab Awad8d5d9dd2015-03-12 11:11:06 -0700256 synchronized (mLock) {
257 try {
258 PhoneAccountHandle accountHandle = mPhoneAccountRegistrar.getSimCallManager();
259 if (!isVisibleToCaller(accountHandle)) {
260 Log.w(this, "%s is not visible for the calling user", accountHandle);
261 return null;
262 }
263 return accountHandle;
264 } catch (Exception e) {
265 Log.e(this, e, "getSimCallManager");
266 throw e;
Santos Cordonf987d1a2014-12-02 03:37:03 -0800267 }
Santos Cordonf987d1a2014-12-02 03:37:03 -0800268 }
269 }
270
271 @Override
272 public void setSimCallManager(PhoneAccountHandle accountHandle) {
Ihab Awad8d5d9dd2015-03-12 11:11:06 -0700273 synchronized (mLock) {
274 enforceModifyPermission();
275 try {
276 mPhoneAccountRegistrar.setSimCallManager(accountHandle);
277 } catch (Exception e) {
278 Log.e(this, e, "setSimCallManager");
279 throw e;
280 }
Santos Cordonf987d1a2014-12-02 03:37:03 -0800281 }
282 }
283
284 @Override
Svet Ganov09611182015-04-16 12:29:01 -0700285 public List<PhoneAccountHandle> getSimCallManagers(String callingPackage) {
Ihab Awad8d5d9dd2015-03-12 11:11:06 -0700286 synchronized (mLock) {
Svet Ganov38f1a4d2015-04-17 15:28:03 -0700287 if (!canReadPhoneState(callingPackage, "getSimCallManagers")) {
Svet Ganov09611182015-04-16 12:29:01 -0700288 return Collections.emptyList();
289 }
290
Ihab Awad8d5d9dd2015-03-12 11:11:06 -0700291 long token = Binder.clearCallingIdentity();
292 try {
Santos Cordonebf2d0f2015-05-15 10:28:29 -0700293 // TODO: Does this isVisible check actually work considering we are clearing
294 // the calling identity?
Ihab Awad8d5d9dd2015-03-12 11:11:06 -0700295 return filterForAccountsVisibleToCaller(
296 mPhoneAccountRegistrar.getConnectionManagerPhoneAccounts());
297 } catch (Exception e) {
298 Log.e(this, e, "getSimCallManagers");
299 throw e;
300 } finally {
301 Binder.restoreCallingIdentity(token);
302 }
Santos Cordonf987d1a2014-12-02 03:37:03 -0800303 }
304 }
305
306 @Override
307 public void registerPhoneAccount(PhoneAccount account) {
Ihab Awad8d5d9dd2015-03-12 11:11:06 -0700308 synchronized (mLock) {
309 try {
310 enforcePhoneAccountModificationForPackage(
311 account.getAccountHandle().getComponentName().getPackageName());
312 if (account.hasCapabilities(PhoneAccount.CAPABILITY_CALL_PROVIDER)) {
313 enforceRegisterCallProviderPermission();
314 }
315 if (account.hasCapabilities(PhoneAccount.CAPABILITY_SIM_SUBSCRIPTION)) {
316 enforceRegisterSimSubscriptionPermission();
317 }
318 if (account.hasCapabilities(PhoneAccount.CAPABILITY_CONNECTION_MANAGER)) {
319 enforceRegisterConnectionManagerPermission();
320 }
321 if (account.hasCapabilities(PhoneAccount.CAPABILITY_MULTI_USER)) {
322 enforceRegisterMultiUser();
323 }
324 enforceUserHandleMatchesCaller(account.getAccountHandle());
Santos Cordonf987d1a2014-12-02 03:37:03 -0800325
Ihab Awad8d5d9dd2015-03-12 11:11:06 -0700326 mPhoneAccountRegistrar.registerPhoneAccount(account);
Santos Cordon73853962015-02-27 15:13:35 -0800327
Ihab Awad8d5d9dd2015-03-12 11:11:06 -0700328 // Broadcast an intent indicating the phone account which was registered.
329 long token = Binder.clearCallingIdentity();
Yorke Lee58061752015-05-04 11:06:26 -0700330 try {
331 Intent intent = new Intent(TelecomManager.ACTION_PHONE_ACCOUNT_REGISTERED);
332 intent.putExtra(TelecomManager.EXTRA_PHONE_ACCOUNT_HANDLE,
333 account.getAccountHandle());
334 Log.i(this, "Sending phone-account intent as user");
335 mContext.sendBroadcastAsUser(intent, UserHandle.ALL,
336 PERMISSION_PROCESS_PHONE_ACCOUNT_REGISTRATION);
337 } finally {
338 Binder.restoreCallingIdentity(token);
339 }
Ihab Awad8d5d9dd2015-03-12 11:11:06 -0700340 } catch (Exception e) {
341 Log.e(this, e, "registerPhoneAccount %s", account);
342 throw e;
343 }
Santos Cordonf987d1a2014-12-02 03:37:03 -0800344 }
345 }
346
347 @Override
348 public void unregisterPhoneAccount(PhoneAccountHandle accountHandle) {
Ihab Awad8d5d9dd2015-03-12 11:11:06 -0700349 synchronized (mLock) {
350 try {
351 enforcePhoneAccountModificationForPackage(
352 accountHandle.getComponentName().getPackageName());
353 enforceUserHandleMatchesCaller(accountHandle);
354 mPhoneAccountRegistrar.unregisterPhoneAccount(accountHandle);
355 } catch (Exception e) {
356 Log.e(this, e, "unregisterPhoneAccount %s", accountHandle);
357 throw e;
358 }
Santos Cordonf987d1a2014-12-02 03:37:03 -0800359 }
360 }
361
362 @Override
363 public void clearAccounts(String packageName) {
Ihab Awad8d5d9dd2015-03-12 11:11:06 -0700364 synchronized (mLock) {
365 try {
366 enforcePhoneAccountModificationForPackage(packageName);
367 mPhoneAccountRegistrar
368 .clearAccounts(packageName, Binder.getCallingUserHandle());
369 } catch (Exception e) {
370 Log.e(this, e, "clearAccounts %s", packageName);
371 throw e;
372 }
Santos Cordonf987d1a2014-12-02 03:37:03 -0800373 }
374 }
375
376 /**
377 * @see android.telecom.TelecomManager#isVoiceMailNumber
378 */
379 @Override
Svet Ganov09611182015-04-16 12:29:01 -0700380 public boolean isVoiceMailNumber(PhoneAccountHandle accountHandle, String number,
381 String callingPackage) {
Ihab Awad8d5d9dd2015-03-12 11:11:06 -0700382 synchronized (mLock) {
Yorke Lee57138a62015-05-18 18:18:08 -0700383 if (!canReadPhoneState(callingPackage, "isVoiceMailNumber")) {
Svet Ganov09611182015-04-16 12:29:01 -0700384 return false;
385 }
386
Santos Cordonebf2d0f2015-05-15 10:28:29 -0700387 if (!isVisibleToCaller(accountHandle)) {
388 Log.w(this, "%s is not visible for the calling user", accountHandle);
389 return false;
390 }
391
392 long token = Binder.clearCallingIdentity();
Ihab Awad8d5d9dd2015-03-12 11:11:06 -0700393 try {
Ihab Awad8d5d9dd2015-03-12 11:11:06 -0700394 return mPhoneAccountRegistrar.isVoiceMailNumber(accountHandle, number);
395 } catch (Exception e) {
396 Log.e(this, e, "getSubscriptionIdForPhoneAccount");
397 throw e;
Santos Cordonebf2d0f2015-05-15 10:28:29 -0700398 } finally {
399 Binder.restoreCallingIdentity(token);
Santos Cordonf987d1a2014-12-02 03:37:03 -0800400 }
Santos Cordonf987d1a2014-12-02 03:37:03 -0800401 }
402 }
403
404 /**
Yorke Leefb5ec302015-04-15 16:15:55 -0700405 * @see android.telecom.TelecomManager#getVoiceMailNumber
Santos Cordonf987d1a2014-12-02 03:37:03 -0800406 */
407 @Override
Svet Ganov09611182015-04-16 12:29:01 -0700408 public String getVoiceMailNumber(PhoneAccountHandle accountHandle, String callingPackage) {
Ihab Awad8d5d9dd2015-03-12 11:11:06 -0700409 synchronized (mLock) {
Yorke Lee57138a62015-05-18 18:18:08 -0700410 if (!canReadPhoneState(callingPackage, "getVoiceMailNumber")) {
Svet Ganov09611182015-04-16 12:29:01 -0700411 return null;
412 }
413
Ihab Awad8d5d9dd2015-03-12 11:11:06 -0700414 try {
415 if (!isVisibleToCaller(accountHandle)) {
416 Log.w(this, "%s is not visible for the calling user", accountHandle);
Yorke Leefb5ec302015-04-15 16:15:55 -0700417 return null;
Ihab Awad8d5d9dd2015-03-12 11:11:06 -0700418 }
Santos Cordonf987d1a2014-12-02 03:37:03 -0800419
Ihab Awad8d5d9dd2015-03-12 11:11:06 -0700420 int subId = SubscriptionManager.getDefaultVoiceSubId();
421 if (accountHandle != null) {
422 subId = mPhoneAccountRegistrar
423 .getSubscriptionIdForPhoneAccount(accountHandle);
424 }
Yorke Leefb5ec302015-04-15 16:15:55 -0700425 return getTelephonyManager().getVoiceMailNumber(subId);
Ihab Awad8d5d9dd2015-03-12 11:11:06 -0700426 } catch (Exception e) {
427 Log.e(this, e, "getSubscriptionIdForPhoneAccount");
428 throw e;
Ihab Awad78a5e6b2015-02-06 10:13:05 -0800429 }
Santos Cordonf987d1a2014-12-02 03:37:03 -0800430 }
431 }
432
433 /**
Nancy Chenba304752015-01-24 23:29:22 -0800434 * @see android.telecom.TelecomManager#getLine1Number
435 */
436 @Override
Svet Ganov09611182015-04-16 12:29:01 -0700437 public String getLine1Number(PhoneAccountHandle accountHandle, String callingPackage) {
Yorke Lee57138a62015-05-18 18:18:08 -0700438 if (!canReadPhoneState(callingPackage, "getLine1Number")) {
Svet Ganov09611182015-04-16 12:29:01 -0700439 return null;
440 }
441
Ihab Awad8d5d9dd2015-03-12 11:11:06 -0700442 synchronized (mLock) {
Santos Cordonebf2d0f2015-05-15 10:28:29 -0700443 if (!isVisibleToCaller(accountHandle)) {
444 Log.w(this, "%s is not visible for the calling user", accountHandle);
445 return null;
446 }
447
448 long token = Binder.clearCallingIdentity();
Ihab Awad8d5d9dd2015-03-12 11:11:06 -0700449 try {
Ihab Awad8d5d9dd2015-03-12 11:11:06 -0700450 int subId =
451 mPhoneAccountRegistrar.getSubscriptionIdForPhoneAccount(accountHandle);
452 return getTelephonyManager().getLine1NumberForSubscriber(subId);
453 } catch (Exception e) {
454 Log.e(this, e, "getSubscriptionIdForPhoneAccount");
455 throw e;
Santos Cordonebf2d0f2015-05-15 10:28:29 -0700456 } finally {
457 Binder.restoreCallingIdentity(token);
Nancy Chenba304752015-01-24 23:29:22 -0800458 }
Nancy Chenba304752015-01-24 23:29:22 -0800459 }
460 }
461
462 /**
Santos Cordonf987d1a2014-12-02 03:37:03 -0800463 * @see android.telecom.TelecomManager#silenceRinger
464 */
465 @Override
Yorke Lee53101962015-04-29 16:25:29 -0700466 public void silenceRinger(String callingPackage) {
Ihab Awad8d5d9dd2015-03-12 11:11:06 -0700467 synchronized (mLock) {
Yorke Leecb0bd8a2015-05-18 11:57:14 -0700468 enforcePermissionOrPrivilegedDialer(MODIFY_PHONE_STATE, callingPackage);
Santos Cordonebf2d0f2015-05-15 10:28:29 -0700469
470 long token = Binder.clearCallingIdentity();
471 try {
472 mCallsManager.getRinger().silence();
473 } finally {
474 Binder.restoreCallingIdentity(token);
475 }
Ihab Awad8d5d9dd2015-03-12 11:11:06 -0700476 }
Santos Cordonf987d1a2014-12-02 03:37:03 -0800477 }
478
479 /**
480 * @see android.telecom.TelecomManager#getDefaultPhoneApp
Yorke Lee5b3fc0a2015-04-23 17:42:57 -0700481 * @deprecated - Use {@link android.telecom.TelecomManager#getDefaultDialerPackage()}
482 * instead.
Santos Cordonf987d1a2014-12-02 03:37:03 -0800483 */
484 @Override
485 public ComponentName getDefaultPhoneApp() {
Ihab Awad8d5d9dd2015-03-12 11:11:06 -0700486 // No need to synchronize
Santos Cordonf987d1a2014-12-02 03:37:03 -0800487 Resources resources = mContext.getResources();
488 return new ComponentName(
489 resources.getString(R.string.ui_default_package),
490 resources.getString(R.string.dialer_default_class));
491 }
492
493 /**
Yorke Lee5291d4a2015-04-24 16:42:36 -0700494 * @return the package name of the current user-selected default dialer. If no default
495 * has been selected, the package name of the system dialer is returned. If
496 * neither exists, then {@code null} is returned.
Yorke Lee5b3fc0a2015-04-23 17:42:57 -0700497 * @see android.telecom.TelecomManager#getDefaultDialerPackage
498 */
499 @Override
500 public String getDefaultDialerPackage() {
Yorke Lee29c003e2015-05-04 17:09:27 -0700501 final long token = Binder.clearCallingIdentity();
502 try {
503 return DefaultDialerManager.getDefaultDialerApplication(mContext);
504 } finally {
505 Binder.restoreCallingIdentity(token);
506 }
Yorke Lee5b3fc0a2015-04-23 17:42:57 -0700507 }
508
509 /**
510 * @see android.telecom.TelecomManager#getSystemDialerPackage
511 */
512 @Override
513 public String getSystemDialerPackage() {
514 return mContext.getResources().getString(R.string.ui_default_package);
515 }
516
517 /**
Santos Cordonf987d1a2014-12-02 03:37:03 -0800518 * @see android.telecom.TelecomManager#isInCall
519 */
520 @Override
Svet Ganov09611182015-04-16 12:29:01 -0700521 public boolean isInCall(String callingPackage) {
Svet Ganov38f1a4d2015-04-17 15:28:03 -0700522 if (!canReadPhoneState(callingPackage, "isInCall")) {
523 return false;
Svet Ganov09611182015-04-16 12:29:01 -0700524 }
525
Ihab Awad8d5d9dd2015-03-12 11:11:06 -0700526 synchronized (mLock) {
Ihab Awad8d5d9dd2015-03-12 11:11:06 -0700527 final int callState = mCallsManager.getCallState();
528 return callState == TelephonyManager.CALL_STATE_OFFHOOK
529 || callState == TelephonyManager.CALL_STATE_RINGING;
530 }
Santos Cordonf987d1a2014-12-02 03:37:03 -0800531 }
532
533 /**
534 * @see android.telecom.TelecomManager#isRinging
535 */
536 @Override
Svet Ganov09611182015-04-16 12:29:01 -0700537 public boolean isRinging(String callingPackage) {
Svet Ganov38f1a4d2015-04-17 15:28:03 -0700538 if (!canReadPhoneState(callingPackage, "isRinging")) {
539 return false;
Svet Ganov09611182015-04-16 12:29:01 -0700540 }
541
Ihab Awad8d5d9dd2015-03-12 11:11:06 -0700542 synchronized (mLock) {
Ihab Awad8d5d9dd2015-03-12 11:11:06 -0700543 return mCallsManager.getCallState() == TelephonyManager.CALL_STATE_RINGING;
544 }
Santos Cordonf987d1a2014-12-02 03:37:03 -0800545 }
546
547 /**
548 * @see TelecomManager#getCallState
549 */
550 @Override
551 public int getCallState() {
Ihab Awad8d5d9dd2015-03-12 11:11:06 -0700552 synchronized (mLock) {
553 return mCallsManager.getCallState();
554 }
Santos Cordonf987d1a2014-12-02 03:37:03 -0800555 }
556
557 /**
558 * @see android.telecom.TelecomManager#endCall
559 */
560 @Override
561 public boolean endCall() {
Ihab Awad8d5d9dd2015-03-12 11:11:06 -0700562 synchronized (mLock) {
563 enforceModifyPermission();
Santos Cordonebf2d0f2015-05-15 10:28:29 -0700564
565 long token = Binder.clearCallingIdentity();
566 try {
567 return endCallInternal();
568 } finally {
569 Binder.restoreCallingIdentity(token);
570 }
Ihab Awad8d5d9dd2015-03-12 11:11:06 -0700571 }
Santos Cordonf987d1a2014-12-02 03:37:03 -0800572 }
573
574 /**
575 * @see android.telecom.TelecomManager#acceptRingingCall
576 */
577 @Override
578 public void acceptRingingCall() {
Ihab Awad8d5d9dd2015-03-12 11:11:06 -0700579 synchronized (mLock) {
580 enforceModifyPermission();
Santos Cordonebf2d0f2015-05-15 10:28:29 -0700581
582 long token = Binder.clearCallingIdentity();
583 try {
584 acceptRingingCallInternal();
585 } finally {
586 Binder.restoreCallingIdentity(token);
587 }
Ihab Awad8d5d9dd2015-03-12 11:11:06 -0700588 }
Santos Cordonf987d1a2014-12-02 03:37:03 -0800589 }
590
591 /**
592 * @see android.telecom.TelecomManager#showInCallScreen
593 */
594 @Override
Svet Ganov09611182015-04-16 12:29:01 -0700595 public void showInCallScreen(boolean showDialpad, String callingPackage) {
Yorke Lee57138a62015-05-18 18:18:08 -0700596 if (!canReadPhoneState(callingPackage, "showInCallScreen")) {
Svet Ganov09611182015-04-16 12:29:01 -0700597 return;
598 }
599
Ihab Awad8d5d9dd2015-03-12 11:11:06 -0700600 synchronized (mLock) {
Santos Cordonebf2d0f2015-05-15 10:28:29 -0700601
602 long token = Binder.clearCallingIdentity();
603 try {
604 mCallsManager.getInCallController().bringToForeground(showDialpad);
605 } finally {
606 Binder.restoreCallingIdentity(token);
607 }
Ihab Awad8d5d9dd2015-03-12 11:11:06 -0700608 }
Santos Cordonf987d1a2014-12-02 03:37:03 -0800609 }
610
611 /**
612 * @see android.telecom.TelecomManager#cancelMissedCallsNotification
613 */
614 @Override
Yorke Lee53101962015-04-29 16:25:29 -0700615 public void cancelMissedCallsNotification(String callingPackage) {
Ihab Awad8d5d9dd2015-03-12 11:11:06 -0700616 synchronized (mLock) {
Yorke Leecb0bd8a2015-05-18 11:57:14 -0700617 enforcePermissionOrPrivilegedDialer(MODIFY_PHONE_STATE, callingPackage);
Santos Cordonebf2d0f2015-05-15 10:28:29 -0700618 long token = Binder.clearCallingIdentity();
619 try {
620 mCallsManager.getMissedCallNotifier().clearMissedCalls();
621 } finally {
622 Binder.restoreCallingIdentity(token);
623 }
Ihab Awad8d5d9dd2015-03-12 11:11:06 -0700624 }
Santos Cordonf987d1a2014-12-02 03:37:03 -0800625 }
626
627 /**
628 * @see android.telecom.TelecomManager#handleMmi
629 */
630 @Override
Yorke Lee53101962015-04-29 16:25:29 -0700631 public boolean handlePinMmi(String dialString, String callingPackage) {
Ihab Awad8d5d9dd2015-03-12 11:11:06 -0700632 synchronized (mLock) {
Yorke Leecb0bd8a2015-05-18 11:57:14 -0700633 enforcePermissionOrPrivilegedDialer(MODIFY_PHONE_STATE, callingPackage);
Santos Cordonf987d1a2014-12-02 03:37:03 -0800634
Ihab Awad8d5d9dd2015-03-12 11:11:06 -0700635 // Switch identity so that TelephonyManager checks Telecom's permissions instead.
636 long token = Binder.clearCallingIdentity();
637 boolean retval = false;
638 try {
639 retval = getTelephonyManager().handlePinMmi(dialString);
640 } finally {
641 Binder.restoreCallingIdentity(token);
642 }
643
644 return retval;
Santos Cordonf987d1a2014-12-02 03:37:03 -0800645 }
Santos Cordonf987d1a2014-12-02 03:37:03 -0800646 }
647
648 /**
649 * @see android.telecom.TelecomManager#handleMmi
650 */
651 @Override
Ihab Awad8d5d9dd2015-03-12 11:11:06 -0700652 public boolean handlePinMmiForPhoneAccount(
653 PhoneAccountHandle accountHandle,
Yorke Lee53101962015-04-29 16:25:29 -0700654 String dialString,
655 String callingPackage) {
Ihab Awad8d5d9dd2015-03-12 11:11:06 -0700656 synchronized (mLock) {
Yorke Leecb0bd8a2015-05-18 11:57:14 -0700657 enforcePermissionOrPrivilegedDialer(MODIFY_PHONE_STATE, callingPackage);
Santos Cordonf987d1a2014-12-02 03:37:03 -0800658
Ihab Awad8d5d9dd2015-03-12 11:11:06 -0700659 if (!isVisibleToCaller(accountHandle)) {
660 Log.w(this, "%s is not visible for the calling user", accountHandle);
661 return false;
662 }
663
664 // Switch identity so that TelephonyManager checks Telecom's permissions instead.
665 long token = Binder.clearCallingIdentity();
666 boolean retval = false;
667 try {
668 int subId = mPhoneAccountRegistrar
669 .getSubscriptionIdForPhoneAccount(accountHandle);
670 retval = getTelephonyManager().handlePinMmiForSubscriber(subId, dialString);
671 } finally {
672 Binder.restoreCallingIdentity(token);
673 }
674
675 return retval;
Santos Cordonf987d1a2014-12-02 03:37:03 -0800676 }
Santos Cordonf987d1a2014-12-02 03:37:03 -0800677 }
678
679 /**
680 * @see android.telecom.TelecomManager#getAdnUriForPhoneAccount
681 */
682 @Override
Yorke Lee53101962015-04-29 16:25:29 -0700683 public Uri getAdnUriForPhoneAccount(PhoneAccountHandle accountHandle,
684 String callingPackage) {
Ihab Awad8d5d9dd2015-03-12 11:11:06 -0700685 synchronized (mLock) {
Yorke Leecb0bd8a2015-05-18 11:57:14 -0700686 enforcePermissionOrPrivilegedDialer(MODIFY_PHONE_STATE, callingPackage);
Santos Cordonf987d1a2014-12-02 03:37:03 -0800687
Ihab Awad8d5d9dd2015-03-12 11:11:06 -0700688 if (!isVisibleToCaller(accountHandle)) {
689 Log.w(this, "%s is not visible for the calling user", accountHandle);
690 return null;
691 }
692
693 // Switch identity so that TelephonyManager checks Telecom's permissions instead.
694 long token = Binder.clearCallingIdentity();
695 String retval = "content://icc/adn/";
696 try {
697 long subId = mPhoneAccountRegistrar
698 .getSubscriptionIdForPhoneAccount(accountHandle);
699 retval = retval + "subId/" + subId;
700 } finally {
701 Binder.restoreCallingIdentity(token);
702 }
703
704 return Uri.parse(retval);
Santos Cordonf987d1a2014-12-02 03:37:03 -0800705 }
Santos Cordonf987d1a2014-12-02 03:37:03 -0800706 }
707
708 /**
709 * @see android.telecom.TelecomManager#isTtySupported
710 */
711 @Override
Svet Ganov09611182015-04-16 12:29:01 -0700712 public boolean isTtySupported(String callingPackage) {
Svet Ganov38f1a4d2015-04-17 15:28:03 -0700713 if (!canReadPhoneState(callingPackage, "hasVoiceMailNumber")) {
714 return false;
Svet Ganov09611182015-04-16 12:29:01 -0700715 }
716
Ihab Awad8d5d9dd2015-03-12 11:11:06 -0700717 synchronized (mLock) {
Ihab Awad8d5d9dd2015-03-12 11:11:06 -0700718 return mCallsManager.isTtySupported();
719 }
Santos Cordonf987d1a2014-12-02 03:37:03 -0800720 }
721
722 /**
723 * @see android.telecom.TelecomManager#getCurrentTtyMode
724 */
725 @Override
Svet Ganov09611182015-04-16 12:29:01 -0700726 public int getCurrentTtyMode(String callingPackage) {
Svet Ganov38f1a4d2015-04-17 15:28:03 -0700727 if (!canReadPhoneState(callingPackage, "getCurrentTtyMode")) {
Svet Ganov09611182015-04-16 12:29:01 -0700728 return TelecomManager.TTY_MODE_OFF;
729 }
730
Ihab Awad8d5d9dd2015-03-12 11:11:06 -0700731 synchronized (mLock) {
Ihab Awad8d5d9dd2015-03-12 11:11:06 -0700732 return mCallsManager.getCurrentTtyMode();
733 }
Santos Cordonf987d1a2014-12-02 03:37:03 -0800734 }
735
736 /**
737 * @see android.telecom.TelecomManager#addNewIncomingCall
738 */
739 @Override
740 public void addNewIncomingCall(PhoneAccountHandle phoneAccountHandle, Bundle extras) {
Ihab Awad8d5d9dd2015-03-12 11:11:06 -0700741 synchronized (mLock) {
742 Log.i(this, "Adding new incoming call with phoneAccountHandle %s",
743 phoneAccountHandle);
744 if (phoneAccountHandle != null && phoneAccountHandle.getComponentName() != null) {
745 mAppOpsManager.checkPackage(
746 Binder.getCallingUid(),
Sailesh Nepal2a98c972015-03-04 15:43:15 -0800747 phoneAccountHandle.getComponentName().getPackageName());
Ihab Awad8d5d9dd2015-03-12 11:11:06 -0700748
Sailesh Nepal2a98c972015-03-04 15:43:15 -0800749 // Make sure it doesn't cross the UserHandle boundary
750 enforceUserHandleMatchesCaller(phoneAccountHandle);
Sharvil Nanavati6d3efb42015-05-14 11:36:40 -0700751 long token = Binder.clearCallingIdentity();
Santos Cordonf987d1a2014-12-02 03:37:03 -0800752
Sharvil Nanavati6d3efb42015-05-14 11:36:40 -0700753 try {
754 Intent intent = new Intent(TelecomManager.ACTION_INCOMING_CALL);
755 intent.putExtra(TelecomManager.EXTRA_PHONE_ACCOUNT_HANDLE,
756 phoneAccountHandle);
757 intent.putExtra(CallIntentProcessor.KEY_IS_INCOMING_CALL, true);
758 if (extras != null) {
759 intent.putExtra(TelecomManager.EXTRA_INCOMING_CALL_EXTRAS, extras);
760 }
761 CallIntentProcessor.processIncomingCallIntent(mCallsManager, intent);
762 } finally {
763 Binder.restoreCallingIdentity(token);
Ihab Awad8d5d9dd2015-03-12 11:11:06 -0700764 }
Ihab Awad8d5d9dd2015-03-12 11:11:06 -0700765 } else {
766 Log.w(this,
767 "Null phoneAccountHandle. Ignoring request to add new incoming call");
Santos Cordonf987d1a2014-12-02 03:37:03 -0800768 }
Santos Cordonf987d1a2014-12-02 03:37:03 -0800769 }
770 }
771
772 /**
773 * @see android.telecom.TelecomManager#addNewUnknownCall
774 */
775 @Override
776 public void addNewUnknownCall(PhoneAccountHandle phoneAccountHandle, Bundle extras) {
Ihab Awad8d5d9dd2015-03-12 11:11:06 -0700777 synchronized (mLock) {
David Stevens07852742015-04-10 18:22:47 -0700778 if (phoneAccountHandle != null && phoneAccountHandle.getComponentName() != null) {
Ihab Awad8d5d9dd2015-03-12 11:11:06 -0700779 mAppOpsManager.checkPackage(
780 Binder.getCallingUid(),
781 phoneAccountHandle.getComponentName().getPackageName());
Santos Cordonf987d1a2014-12-02 03:37:03 -0800782
Ihab Awad8d5d9dd2015-03-12 11:11:06 -0700783 // Make sure it doesn't cross the UserHandle boundary
784 enforceUserHandleMatchesCaller(phoneAccountHandle);
Sharvil Nanavati6d3efb42015-05-14 11:36:40 -0700785 long token = Binder.clearCallingIdentity();
Santos Cordonf987d1a2014-12-02 03:37:03 -0800786
Sharvil Nanavati6d3efb42015-05-14 11:36:40 -0700787 try {
788 Intent intent = new Intent(TelecomManager.ACTION_NEW_UNKNOWN_CALL);
789 intent.putExtras(extras);
790 intent.putExtra(CallIntentProcessor.KEY_IS_UNKNOWN_CALL, true);
791 intent.putExtra(TelecomManager.EXTRA_PHONE_ACCOUNT_HANDLE,
792 phoneAccountHandle);
793 CallIntentProcessor.processUnknownCallIntent(mCallsManager, intent);
794 } finally {
795 Binder.restoreCallingIdentity(token);
796 }
Ihab Awad8d5d9dd2015-03-12 11:11:06 -0700797 } else {
798 Log.i(this,
799 "Null phoneAccountHandle or not initiated by Telephony. " +
800 "Ignoring request to add new unknown call.");
801 }
Santos Cordonf987d1a2014-12-02 03:37:03 -0800802 }
803 }
Tyler Gunn47689862014-12-17 17:10:28 -0800804
805 /**
Yorke Leea3a3adc2015-04-23 12:49:01 -0700806 * @see android.telecom.TelecomManager#placeCall
807 */
808 @Override
809 public void placeCall(Uri handle, Bundle extras, String callingPackage) {
810 enforceCallingPackage(callingPackage);
Yorke Lee57138a62015-05-18 18:18:08 -0700811 if (!canCallPhone(callingPackage, "placeCall")) {
812 throw new SecurityException("Package " + callingPackage
813 + " is not allowed to place phone calls");
814 }
Yorke Leecb0bd8a2015-05-18 11:57:14 -0700815
Yorke Leea3a3adc2015-04-23 12:49:01 -0700816 synchronized (mLock) {
Yorke Leeb3feab52015-04-30 12:35:16 -0700817 final UserHandle userHandle = Binder.getCallingUserHandle();
Yorke Leeb7910662015-04-24 12:00:19 -0700818 long token = Binder.clearCallingIdentity();
Yorke Lee58061752015-05-04 11:06:26 -0700819 try {
820 final Intent intent = new Intent(Intent.ACTION_CALL, handle);
821 intent.putExtras(extras);
822 new UserCallIntentProcessor(mContext, userHandle).processIntent(intent,
823 callingPackage);
824 } finally {
825 Binder.restoreCallingIdentity(token);
826 }
Yorke Leea3a3adc2015-04-23 12:49:01 -0700827 }
828 }
829
830 /**
Tyler Gunn47689862014-12-17 17:10:28 -0800831 * Dumps the current state of the TelecomService. Used when generating problem reports.
832 *
833 * @param fd The file descriptor.
834 * @param writer The print writer to dump the state to.
835 * @param args Optional dump arguments.
836 */
837 @Override
838 protected void dump(FileDescriptor fd, final PrintWriter writer, String[] args) {
839 if (mContext.checkCallingOrSelfPermission(
840 android.Manifest.permission.DUMP)
841 != PackageManager.PERMISSION_GRANTED) {
842 writer.println("Permission Denial: can't dump TelecomService " +
843 "from from pid=" + Binder.getCallingPid() + ", uid=" +
844 Binder.getCallingUid());
845 return;
846 }
847
848 final IndentingPrintWriter pw = new IndentingPrintWriter(writer, " ");
Ihab Awad8de76912015-02-17 12:25:52 -0800849 if (mCallsManager != null) {
Ihab Awad78a5e6b2015-02-06 10:13:05 -0800850 pw.println("CallsManager: ");
Tyler Gunn47689862014-12-17 17:10:28 -0800851 pw.increaseIndent();
Ihab Awad8de76912015-02-17 12:25:52 -0800852 mCallsManager.dump(pw);
Tyler Gunn47689862014-12-17 17:10:28 -0800853 pw.decreaseIndent();
854
Ihab Awad78a5e6b2015-02-06 10:13:05 -0800855 pw.println("PhoneAccountRegistrar: ");
Tyler Gunn47689862014-12-17 17:10:28 -0800856 pw.increaseIndent();
Ihab Awad8d5d9dd2015-03-12 11:11:06 -0700857 mPhoneAccountRegistrar.dump(pw);
Tyler Gunn47689862014-12-17 17:10:28 -0800858 pw.decreaseIndent();
859 }
Santos Cordon2685dab2015-04-17 17:12:09 -0700860
861 Log.dumpCallEvents(pw);
Tyler Gunn47689862014-12-17 17:10:28 -0800862 }
Ihab Awad8d5d9dd2015-03-12 11:11:06 -0700863 };
864
865 private Context mContext;
866 private AppOpsManager mAppOpsManager;
867 private UserManager mUserManager;
868 private PackageManager mPackageManager;
869 private CallsManager mCallsManager;
870 private final PhoneAccountRegistrar mPhoneAccountRegistrar;
871 private final TelecomSystem.SyncRoot mLock;
872
873 public TelecomServiceImpl(
874 Context context,
875 CallsManager callsManager,
876 PhoneAccountRegistrar phoneAccountRegistrar,
877 TelecomSystem.SyncRoot lock) {
878 mContext = context;
879 mAppOpsManager = (AppOpsManager) mContext.getSystemService(Context.APP_OPS_SERVICE);
880
881 mUserManager = (UserManager) mContext.getSystemService(Context.USER_SERVICE);
882 mPackageManager = mContext.getPackageManager();
883
884 mCallsManager = callsManager;
885 mLock = lock;
886 mPhoneAccountRegistrar = phoneAccountRegistrar;
887 }
888
Ihab Awadaa383cc2015-03-22 22:12:28 -0700889 public ITelecomService.Stub getBinder() {
Ihab Awad8d5d9dd2015-03-12 11:11:06 -0700890 return mBinderImpl;
Santos Cordonf987d1a2014-12-02 03:37:03 -0800891 }
892
893 //
894 // Supporting methods for the ITelecomService interface implementation.
895 //
896
897 private boolean isVisibleToCaller(PhoneAccountHandle accountHandle) {
898 if (accountHandle == null) {
899 return false;
900 }
Santos Cordon6a212642015-05-08 16:35:23 -0700901 return isVisibleToCaller(mPhoneAccountRegistrar.getPhoneAccount(accountHandle));
Santos Cordonf987d1a2014-12-02 03:37:03 -0800902 }
903
904 private boolean isVisibleToCaller(PhoneAccount account) {
905 if (account == null) {
906 return false;
907 }
908
909 // If this PhoneAccount has CAPABILITY_MULTI_USER, it should be visible to all users and
910 // all profiles. Only Telephony and SIP accounts should have this capability.
911 if (account.hasCapabilities(PhoneAccount.CAPABILITY_MULTI_USER)) {
912 return true;
913 }
914
915 UserHandle phoneAccountUserHandle = account.getAccountHandle().getUserHandle();
916 if (phoneAccountUserHandle == null) {
917 return false;
918 }
919
Sailesh Nepal91fc8092015-02-14 15:44:55 -0800920 if (phoneAccountUserHandle.equals(Binder.getCallingUserHandle())) {
921 return true;
922 }
923
Santos Cordonf987d1a2014-12-02 03:37:03 -0800924 List<UserHandle> profileUserHandles;
Sailesh Nepal91fc8092015-02-14 15:44:55 -0800925 if (UserHandle.getCallingUserId() == UserHandle.USER_OWNER) {
Santos Cordonf987d1a2014-12-02 03:37:03 -0800926 profileUserHandles = mUserManager.getUserProfiles();
927 } else {
928 // Otherwise, it has to be owned by the current caller's profile.
929 profileUserHandles = new ArrayList<>(1);
930 profileUserHandles.add(Binder.getCallingUserHandle());
931 }
932
933 return profileUserHandles.contains(phoneAccountUserHandle);
934 }
935
936 /**
937 * Given a list of {@link PhoneAccountHandle}s, filter them to the ones that the calling
938 * user can see.
939 *
940 * @param phoneAccountHandles Unfiltered list of account handles.
941 *
942 * @return {@link PhoneAccountHandle}s visible to the calling user and its profiles.
943 */
944 private List<PhoneAccountHandle> filterForAccountsVisibleToCaller(
945 List<PhoneAccountHandle> phoneAccountHandles) {
946 List<PhoneAccountHandle> profilePhoneAccountHandles =
947 new ArrayList<>(phoneAccountHandles.size());
948 for (PhoneAccountHandle phoneAccountHandle : phoneAccountHandles) {
949 if (isVisibleToCaller(phoneAccountHandle)) {
950 profilePhoneAccountHandles.add(phoneAccountHandle);
951 }
952 }
953 return profilePhoneAccountHandles;
954 }
955
956 private boolean isCallerSystemApp() {
957 int uid = Binder.getCallingUid();
958 String[] packages = mPackageManager.getPackagesForUid(uid);
959 for (String packageName : packages) {
960 if (isPackageSystemApp(packageName)) {
961 return true;
962 }
963 }
964 return false;
965 }
966
967 private boolean isPackageSystemApp(String packageName) {
968 try {
969 ApplicationInfo applicationInfo = mPackageManager.getApplicationInfo(packageName,
970 PackageManager.GET_META_DATA);
971 if ((applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0) {
972 return true;
973 }
974 } catch (PackageManager.NameNotFoundException e) {
975 }
976 return false;
977 }
978
979 private void acceptRingingCallInternal() {
Ihab Awad8de76912015-02-17 12:25:52 -0800980 Call call = mCallsManager.getFirstCallWithState(CallState.RINGING);
Santos Cordonf987d1a2014-12-02 03:37:03 -0800981 if (call != null) {
982 call.answer(call.getVideoState());
983 }
984 }
985
986 private boolean endCallInternal() {
987 // Always operate on the foreground call if one exists, otherwise get the first call in
988 // priority order by call-state.
Ihab Awad8de76912015-02-17 12:25:52 -0800989 Call call = mCallsManager.getForegroundCall();
Santos Cordonf987d1a2014-12-02 03:37:03 -0800990 if (call == null) {
Ihab Awad8de76912015-02-17 12:25:52 -0800991 call = mCallsManager.getFirstCallWithState(
Santos Cordonf987d1a2014-12-02 03:37:03 -0800992 CallState.ACTIVE,
993 CallState.DIALING,
994 CallState.RINGING,
995 CallState.ON_HOLD);
996 }
997
998 if (call != null) {
999 if (call.getState() == CallState.RINGING) {
1000 call.reject(false /* rejectWithMessage */, null);
1001 } else {
1002 call.disconnect();
1003 }
1004 return true;
1005 }
1006
1007 return false;
1008 }
1009
1010 private void enforcePhoneAccountModificationForPackage(String packageName) {
1011 // TODO: Use a new telecomm permission for this instead of reusing modify.
1012
Yorke Leecb0bd8a2015-05-18 11:57:14 -07001013 int result = mContext.checkCallingOrSelfPermission(MODIFY_PHONE_STATE);
Santos Cordonf987d1a2014-12-02 03:37:03 -08001014
1015 // Callers with MODIFY_PHONE_STATE can use the PhoneAccount mechanism to implement
1016 // built-in behavior even when PhoneAccounts are not exposed as a third-part API. They
1017 // may also modify PhoneAccounts on behalf of any 'packageName'.
1018
1019 if (result != PackageManager.PERMISSION_GRANTED) {
1020 // Other callers are only allowed to modify PhoneAccounts if the relevant system
1021 // feature is enabled ...
1022 enforceConnectionServiceFeature();
1023 // ... and the PhoneAccounts they refer to are for their own package.
1024 enforceCallingPackage(packageName);
1025 }
1026 }
1027
Yorke Leecb0bd8a2015-05-18 11:57:14 -07001028 private void enforcePermissionOrPrivilegedDialer(String permission, String packageName) {
Yorke Lee53101962015-04-29 16:25:29 -07001029 if (!isPrivilegedDialerCalling(packageName)) {
1030 try {
Yorke Leecb0bd8a2015-05-18 11:57:14 -07001031 enforcePermission(permission);
Yorke Lee53101962015-04-29 16:25:29 -07001032 } catch (SecurityException e) {
Yorke Leecb0bd8a2015-05-18 11:57:14 -07001033 Log.e(this, e, "Caller must be the default or system dialer, or have the permission"
1034 + " %s to perform this operation.", permission);
Yorke Lee53101962015-04-29 16:25:29 -07001035 throw e;
1036 }
Santos Cordonf987d1a2014-12-02 03:37:03 -08001037 }
1038 }
1039
1040 private void enforceCallingPackage(String packageName) {
1041 mAppOpsManager.checkPackage(Binder.getCallingUid(), packageName);
1042 }
1043
1044 private void enforceConnectionServiceFeature() {
1045 enforceFeature(PackageManager.FEATURE_CONNECTION_SERVICE);
1046 }
1047
1048 private void enforceRegisterCallProviderPermission() {
Yorke Leecb0bd8a2015-05-18 11:57:14 -07001049 enforcePermission(REGISTER_CALL_PROVIDER);
Santos Cordonf987d1a2014-12-02 03:37:03 -08001050 }
1051
1052 private void enforceRegisterSimSubscriptionPermission() {
Yorke Leecb0bd8a2015-05-18 11:57:14 -07001053 enforcePermission(REGISTER_SIM_SUBSCRIPTION);
Santos Cordonf987d1a2014-12-02 03:37:03 -08001054 }
1055
1056 private void enforceRegisterConnectionManagerPermission() {
Yorke Leecb0bd8a2015-05-18 11:57:14 -07001057 enforcePermission(REGISTER_CONNECTION_MANAGER);
Santos Cordonf987d1a2014-12-02 03:37:03 -08001058 }
1059
Santos Cordonf987d1a2014-12-02 03:37:03 -08001060 private void enforceModifyPermission() {
Yorke Leecb0bd8a2015-05-18 11:57:14 -07001061 enforcePermission(MODIFY_PHONE_STATE);
Santos Cordonf987d1a2014-12-02 03:37:03 -08001062 }
1063
1064 private void enforcePermission(String permission) {
1065 mContext.enforceCallingOrSelfPermission(permission, null);
1066 }
1067
1068 private void enforceRegisterMultiUser() {
1069 if (!isCallerSystemApp()) {
1070 throw new SecurityException("CAPABILITY_MULTI_USER is only available to system apps.");
1071 }
1072 }
1073
1074 private void enforceUserHandleMatchesCaller(PhoneAccountHandle accountHandle) {
1075 if (!Binder.getCallingUserHandle().equals(accountHandle.getUserHandle())) {
1076 throw new SecurityException("Calling UserHandle does not match PhoneAccountHandle's");
1077 }
1078 }
1079
1080 private void enforceFeature(String feature) {
1081 PackageManager pm = mContext.getPackageManager();
1082 if (!pm.hasSystemFeature(feature)) {
1083 throw new UnsupportedOperationException(
1084 "System does not support feature " + feature);
1085 }
1086 }
1087
Svet Ganov38f1a4d2015-04-17 15:28:03 -07001088 private boolean canReadPhoneState(String callingPackage, String message) {
Yorke Lee57138a62015-05-18 18:18:08 -07001089 // The system/default dialer can always read phone state - so that emergency calls will
1090 // still work.
1091 if (isPrivilegedDialerCalling(callingPackage)) {
1092 return true;
1093 }
1094
Svet Ganov09611182015-04-16 12:29:01 -07001095 // Accessing phone state is gated by a special permission.
Yorke Leecb0bd8a2015-05-18 11:57:14 -07001096 mContext.enforceCallingOrSelfPermission(READ_PHONE_STATE, message);
Svet Ganov09611182015-04-16 12:29:01 -07001097
1098 // Some apps that have the permission can be restricted via app ops.
1099 return mAppOpsManager.noteOp(AppOpsManager.OP_READ_PHONE_STATE,
1100 Binder.getCallingUid(), callingPackage) == AppOpsManager.MODE_ALLOWED;
1101 }
1102
Yorke Leea3a3adc2015-04-23 12:49:01 -07001103 private boolean canCallPhone(String callingPackage, String message) {
Yorke Lee57138a62015-05-18 18:18:08 -07001104 // The system/default dialer can always read phone state - so that emergency calls will
1105 // still work.
1106 if (isPrivilegedDialerCalling(callingPackage)) {
1107 return true;
1108 }
1109
Yorke Leea3a3adc2015-04-23 12:49:01 -07001110 // Accessing phone state is gated by a special permission.
Yorke Leecb0bd8a2015-05-18 11:57:14 -07001111 mContext.enforceCallingOrSelfPermission(CALL_PHONE, message);
Yorke Leea3a3adc2015-04-23 12:49:01 -07001112
1113 // Some apps that have the permission can be restricted via app ops.
1114 return mAppOpsManager.noteOp(AppOpsManager.OP_CALL_PHONE,
1115 Binder.getCallingUid(), callingPackage) == AppOpsManager.MODE_ALLOWED;
1116 }
1117
Sailesh Nepal2a98c972015-03-04 15:43:15 -08001118 private boolean isCallerSimCallManager() {
Etan Cohenb600a5f2015-03-06 17:37:30 -08001119 PhoneAccountHandle accountHandle = TelecomSystem.getInstance().getPhoneAccountRegistrar()
1120 .getSimCallManager();
Sailesh Nepal2a98c972015-03-04 15:43:15 -08001121 if (accountHandle != null) {
1122 try {
1123 mAppOpsManager.checkPackage(
1124 Binder.getCallingUid(), accountHandle.getComponentName().getPackageName());
1125 return true;
1126 } catch (SecurityException e) {
1127 }
1128 }
1129 return false;
1130 }
1131
Yorke Lee53101962015-04-29 16:25:29 -07001132 private boolean isPrivilegedDialerCalling(String callingPackage) {
1133 mAppOpsManager.checkPackage(Binder.getCallingUid(), callingPackage);
1134 return DefaultDialerManager.isDefaultOrSystemDialer(mContext, callingPackage);
Santos Cordonf987d1a2014-12-02 03:37:03 -08001135 }
1136
1137 private TelephonyManager getTelephonyManager() {
1138 return (TelephonyManager)mContext.getSystemService(Context.TELEPHONY_SERVICE);
1139 }
Santos Cordonf987d1a2014-12-02 03:37:03 -08001140}