blob: da9c07b2a291f8e86364864a02f53b8888eb60b5 [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;
Yorke Lee71734c22015-06-02 14:22:56 -070025import static android.Manifest.permission.WRITE_SECURE_SETTINGS;
Yorke Leecb0bd8a2015-05-18 11:57:14 -070026
Santos Cordonf987d1a2014-12-02 03:37:03 -080027import android.app.AppOpsManager;
Santos Cordonf987d1a2014-12-02 03:37:03 -080028import android.content.ComponentName;
29import android.content.Context;
30import android.content.Intent;
31import android.content.pm.ApplicationInfo;
32import android.content.pm.PackageManager;
33import android.content.res.Resources;
34import android.net.Uri;
35import android.os.Binder;
36import android.os.Bundle;
Santos Cordonf987d1a2014-12-02 03:37:03 -080037import android.os.IBinder;
Santos Cordonf987d1a2014-12-02 03:37:03 -080038import android.os.UserHandle;
39import android.os.UserManager;
Yorke Lee5b3fc0a2015-04-23 17:42:57 -070040import android.telecom.DefaultDialerManager;
Santos Cordonf987d1a2014-12-02 03:37:03 -080041import android.telecom.PhoneAccount;
42import android.telecom.PhoneAccountHandle;
43import android.telecom.TelecomManager;
44import android.telephony.SubscriptionManager;
45import android.telephony.TelephonyManager;
46import android.text.TextUtils;
47
48// TODO: Needed for move to system service: import com.android.internal.R;
49import com.android.internal.telecom.ITelecomService;
50import com.android.internal.util.IndentingPrintWriter;
Yorke Leea3a3adc2015-04-23 12:49:01 -070051import com.android.server.telecom.components.UserCallIntentProcessor;
Santos Cordonf987d1a2014-12-02 03:37:03 -080052
53import java.io.FileDescriptor;
54import java.io.PrintWriter;
55import java.util.ArrayList;
Svet Ganov09611182015-04-16 12:29:01 -070056import java.util.Collections;
Santos Cordonf987d1a2014-12-02 03:37:03 -080057import java.util.List;
58
59/**
60 * Implementation of the ITelecom interface.
61 */
Ihab Awad78a5e6b2015-02-06 10:13:05 -080062public class TelecomServiceImpl {
Santos Cordon73853962015-02-27 15:13:35 -080063 private static final String PERMISSION_PROCESS_PHONE_ACCOUNT_REGISTRATION =
64 "android.permission.PROCESS_PHONE_ACCOUNT_REGISTRATION";
65
Ihab Awad8d5d9dd2015-03-12 11:11:06 -070066 private final ITelecomService.Stub mBinderImpl = new ITelecomService.Stub() {
Santos Cordonf987d1a2014-12-02 03:37:03 -080067 @Override
Svet Ganov09611182015-04-16 12:29:01 -070068 public PhoneAccountHandle getDefaultOutgoingPhoneAccount(String uriScheme,
69 String callingPackage) {
Ihab Awad8d5d9dd2015-03-12 11:11:06 -070070 synchronized (mLock) {
Svet Ganov38f1a4d2015-04-17 15:28:03 -070071 if (!canReadPhoneState(callingPackage, "getDefaultOutgoingPhoneAccount")) {
Svet Ganov09611182015-04-16 12:29:01 -070072 return null;
73 }
74
Ihab Awad8d5d9dd2015-03-12 11:11:06 -070075 long token = Binder.clearCallingIdentity();
76 try {
77 PhoneAccountHandle defaultOutgoingPhoneAccount =
Santos Cordon6a212642015-05-08 16:35:23 -070078 mPhoneAccountRegistrar.getOutgoingPhoneAccountForScheme(uriScheme);
Ihab Awad8d5d9dd2015-03-12 11:11:06 -070079 // Make sure that the calling user can see this phone account.
Santos Cordonebf2d0f2015-05-15 10:28:29 -070080 // TODO: Does this isVisible check actually work considering we are clearing
81 // the calling identity?
Ihab Awad8d5d9dd2015-03-12 11:11:06 -070082 if (defaultOutgoingPhoneAccount != null
83 && !isVisibleToCaller(defaultOutgoingPhoneAccount)) {
84 Log.w(this, "No account found for the calling user");
85 return null;
86 }
87 return defaultOutgoingPhoneAccount;
88 } catch (Exception e) {
89 Log.e(this, e, "getDefaultOutgoingPhoneAccount");
90 throw e;
91 } finally {
92 Binder.restoreCallingIdentity(token);
Santos Cordonf987d1a2014-12-02 03:37:03 -080093 }
Santos Cordonf987d1a2014-12-02 03:37:03 -080094 }
95 }
96
97 @Override
98 public PhoneAccountHandle getUserSelectedOutgoingPhoneAccount() {
Ihab Awad8d5d9dd2015-03-12 11:11:06 -070099 synchronized (mLock) {
100 try {
101 PhoneAccountHandle userSelectedOutgoingPhoneAccount =
102 mPhoneAccountRegistrar.getUserSelectedOutgoingPhoneAccount();
103 // Make sure that the calling user can see this phone account.
104 if (!isVisibleToCaller(userSelectedOutgoingPhoneAccount)) {
105 Log.w(this, "No account found for the calling user");
106 return null;
107 }
108 return userSelectedOutgoingPhoneAccount;
109 } catch (Exception e) {
110 Log.e(this, e, "getUserSelectedOutgoingPhoneAccount");
111 throw e;
Santos Cordonf987d1a2014-12-02 03:37:03 -0800112 }
Santos Cordonf987d1a2014-12-02 03:37:03 -0800113 }
114 }
115
116 @Override
117 public void setUserSelectedOutgoingPhoneAccount(PhoneAccountHandle accountHandle) {
Ihab Awad8d5d9dd2015-03-12 11:11:06 -0700118 synchronized (mLock) {
119 enforceModifyPermission();
Santos Cordonebf2d0f2015-05-15 10:28:29 -0700120
121 long token = Binder.clearCallingIdentity();
Ihab Awad8d5d9dd2015-03-12 11:11:06 -0700122 try {
123 mPhoneAccountRegistrar.setUserSelectedOutgoingPhoneAccount(accountHandle);
124 } catch (Exception e) {
125 Log.e(this, e, "setUserSelectedOutgoingPhoneAccount");
126 throw e;
Santos Cordonebf2d0f2015-05-15 10:28:29 -0700127 } finally {
128 Binder.restoreCallingIdentity(token);
Ihab Awad8d5d9dd2015-03-12 11:11:06 -0700129 }
Santos Cordonf987d1a2014-12-02 03:37:03 -0800130 }
131 }
132
133 @Override
Santos Cordonea5cb932015-05-07 16:28:38 -0700134 public List<PhoneAccountHandle> getCallCapablePhoneAccounts(
135 boolean includeDisabledAccounts, String callingPackage) {
Svet Ganov38f1a4d2015-04-17 15:28:03 -0700136 if (!canReadPhoneState(callingPackage, "getDefaultOutgoingPhoneAccount")) {
Svet Ganov09611182015-04-16 12:29:01 -0700137 return Collections.emptyList();
138 }
139
Ihab Awad8d5d9dd2015-03-12 11:11:06 -0700140 synchronized (mLock) {
Ihab Awad8d5d9dd2015-03-12 11:11:06 -0700141 long token = Binder.clearCallingIdentity();
142 try {
Santos Cordonebf2d0f2015-05-15 10:28:29 -0700143 // TODO: Does this isVisible check actually work considering we are clearing
144 // the calling identity?
Ihab Awad8d5d9dd2015-03-12 11:11:06 -0700145 return filterForAccountsVisibleToCaller(
Santos Cordonea5cb932015-05-07 16:28:38 -0700146 mPhoneAccountRegistrar.getCallCapablePhoneAccounts(
147 null, includeDisabledAccounts));
Ihab Awad8d5d9dd2015-03-12 11:11:06 -0700148 } catch (Exception e) {
149 Log.e(this, e, "getCallCapablePhoneAccounts");
150 throw e;
151 } finally {
152 Binder.restoreCallingIdentity(token);
153 }
Santos Cordonf987d1a2014-12-02 03:37:03 -0800154 }
155 }
156
157 @Override
Svet Ganov09611182015-04-16 12:29:01 -0700158 public List<PhoneAccountHandle> getPhoneAccountsSupportingScheme(String uriScheme,
159 String callingPackage) {
Ihab Awad8d5d9dd2015-03-12 11:11:06 -0700160 synchronized (mLock) {
Svet Ganov38f1a4d2015-04-17 15:28:03 -0700161 if (!canReadPhoneState(callingPackage, "getPhoneAccountsSupportingScheme")) {
Svet Ganov09611182015-04-16 12:29:01 -0700162 return Collections.emptyList();
163 }
164
Ihab Awad8d5d9dd2015-03-12 11:11:06 -0700165 long token = Binder.clearCallingIdentity();
166 try {
Santos Cordonebf2d0f2015-05-15 10:28:29 -0700167 // TODO: Does this isVisible check actually work considering we are clearing
168 // the calling identity?
Ihab Awad8d5d9dd2015-03-12 11:11:06 -0700169 return filterForAccountsVisibleToCaller(
Santos Cordonea5cb932015-05-07 16:28:38 -0700170 mPhoneAccountRegistrar.getCallCapablePhoneAccounts(uriScheme, false));
Ihab Awad8d5d9dd2015-03-12 11:11:06 -0700171 } catch (Exception e) {
172 Log.e(this, e, "getPhoneAccountsSupportingScheme %s", uriScheme);
173 throw e;
174 } finally {
175 Binder.restoreCallingIdentity(token);
176 }
Santos Cordonf987d1a2014-12-02 03:37:03 -0800177 }
178 }
179
180 @Override
181 public List<PhoneAccountHandle> getPhoneAccountsForPackage(String packageName) {
Ihab Awad8d5d9dd2015-03-12 11:11:06 -0700182 synchronized (mLock) {
183 try {
184 return filterForAccountsVisibleToCaller(
185 mPhoneAccountRegistrar.getPhoneAccountsForPackage(packageName));
186 } catch (Exception e) {
187 Log.e(this, e, "getPhoneAccountsForPackage %s", packageName);
188 throw e;
189 }
Santos Cordonf987d1a2014-12-02 03:37:03 -0800190 }
191 }
192
193 @Override
194 public PhoneAccount getPhoneAccount(PhoneAccountHandle accountHandle) {
Ihab Awad8d5d9dd2015-03-12 11:11:06 -0700195 synchronized (mLock) {
196 try {
197 if (!isVisibleToCaller(accountHandle)) {
Santos Cordon3188b362015-05-22 13:01:10 -0700198 Log.w(this, "%s is not visible for the calling user [gPA]", accountHandle);
Ihab Awad8d5d9dd2015-03-12 11:11:06 -0700199 return null;
200 }
Santos Cordon6a212642015-05-08 16:35:23 -0700201 // TODO: Do we really want to return for *any* user?
202 return mPhoneAccountRegistrar.getPhoneAccount(accountHandle);
Ihab Awad8d5d9dd2015-03-12 11:11:06 -0700203 } catch (Exception e) {
204 Log.e(this, e, "getPhoneAccount %s", accountHandle);
205 throw e;
Santos Cordonf987d1a2014-12-02 03:37:03 -0800206 }
Santos Cordonf987d1a2014-12-02 03:37:03 -0800207 }
208 }
209
210 @Override
211 public int getAllPhoneAccountsCount() {
Ihab Awad8d5d9dd2015-03-12 11:11:06 -0700212 synchronized (mLock) {
213 try {
214 // This list is pre-filtered for the calling user.
215 return getAllPhoneAccounts().size();
216 } catch (Exception e) {
217 Log.e(this, e, "getAllPhoneAccountsCount");
218 throw e;
219 }
Santos Cordonf987d1a2014-12-02 03:37:03 -0800220 }
221 }
222
223 @Override
224 public List<PhoneAccount> getAllPhoneAccounts() {
Ihab Awad8d5d9dd2015-03-12 11:11:06 -0700225 synchronized (mLock) {
226 try {
227 List<PhoneAccount> allPhoneAccounts = mPhoneAccountRegistrar
228 .getAllPhoneAccounts();
229 List<PhoneAccount> profilePhoneAccounts = new ArrayList<>(
230 allPhoneAccounts.size());
231 for (PhoneAccount phoneAccount : profilePhoneAccounts) {
232 if (isVisibleToCaller(phoneAccount)) {
233 profilePhoneAccounts.add(phoneAccount);
234 }
Santos Cordonf987d1a2014-12-02 03:37:03 -0800235 }
Ihab Awad8d5d9dd2015-03-12 11:11:06 -0700236 return profilePhoneAccounts;
237 } catch (Exception e) {
238 Log.e(this, e, "getAllPhoneAccounts");
239 throw e;
Santos Cordonf987d1a2014-12-02 03:37:03 -0800240 }
Santos Cordonf987d1a2014-12-02 03:37:03 -0800241 }
242 }
243
244 @Override
245 public List<PhoneAccountHandle> getAllPhoneAccountHandles() {
Ihab Awad8d5d9dd2015-03-12 11:11:06 -0700246 synchronized (mLock) {
247 try {
248 return filterForAccountsVisibleToCaller(
249 mPhoneAccountRegistrar.getAllPhoneAccountHandles());
250 } catch (Exception e) {
251 Log.e(this, e, "getAllPhoneAccounts");
252 throw e;
253 }
Santos Cordonf987d1a2014-12-02 03:37:03 -0800254 }
255 }
256
257 @Override
258 public PhoneAccountHandle getSimCallManager() {
Ihab Awad8d5d9dd2015-03-12 11:11:06 -0700259 synchronized (mLock) {
260 try {
261 PhoneAccountHandle accountHandle = mPhoneAccountRegistrar.getSimCallManager();
262 if (!isVisibleToCaller(accountHandle)) {
Santos Cordon3188b362015-05-22 13:01:10 -0700263 Log.w(this, "%s is not visible for the calling user [gsCM]", accountHandle);
Ihab Awad8d5d9dd2015-03-12 11:11:06 -0700264 return null;
265 }
266 return accountHandle;
267 } catch (Exception e) {
268 Log.e(this, e, "getSimCallManager");
269 throw e;
Santos Cordonf987d1a2014-12-02 03:37:03 -0800270 }
Santos Cordonf987d1a2014-12-02 03:37:03 -0800271 }
272 }
273
274 @Override
275 public void setSimCallManager(PhoneAccountHandle accountHandle) {
Ihab Awad8d5d9dd2015-03-12 11:11:06 -0700276 synchronized (mLock) {
277 enforceModifyPermission();
278 try {
279 mPhoneAccountRegistrar.setSimCallManager(accountHandle);
280 } catch (Exception e) {
281 Log.e(this, e, "setSimCallManager");
282 throw e;
283 }
Santos Cordonf987d1a2014-12-02 03:37:03 -0800284 }
285 }
286
287 @Override
Svet Ganov09611182015-04-16 12:29:01 -0700288 public List<PhoneAccountHandle> getSimCallManagers(String callingPackage) {
Ihab Awad8d5d9dd2015-03-12 11:11:06 -0700289 synchronized (mLock) {
Svet Ganov38f1a4d2015-04-17 15:28:03 -0700290 if (!canReadPhoneState(callingPackage, "getSimCallManagers")) {
Svet Ganov09611182015-04-16 12:29:01 -0700291 return Collections.emptyList();
292 }
293
Ihab Awad8d5d9dd2015-03-12 11:11:06 -0700294 long token = Binder.clearCallingIdentity();
295 try {
Santos Cordonebf2d0f2015-05-15 10:28:29 -0700296 // TODO: Does this isVisible check actually work considering we are clearing
297 // the calling identity?
Ihab Awad8d5d9dd2015-03-12 11:11:06 -0700298 return filterForAccountsVisibleToCaller(
299 mPhoneAccountRegistrar.getConnectionManagerPhoneAccounts());
300 } catch (Exception e) {
301 Log.e(this, e, "getSimCallManagers");
302 throw e;
303 } finally {
304 Binder.restoreCallingIdentity(token);
305 }
Santos Cordonf987d1a2014-12-02 03:37:03 -0800306 }
307 }
308
309 @Override
310 public void registerPhoneAccount(PhoneAccount account) {
Ihab Awad8d5d9dd2015-03-12 11:11:06 -0700311 synchronized (mLock) {
312 try {
313 enforcePhoneAccountModificationForPackage(
314 account.getAccountHandle().getComponentName().getPackageName());
Ihab Awad8d5d9dd2015-03-12 11:11:06 -0700315 if (account.hasCapabilities(PhoneAccount.CAPABILITY_SIM_SUBSCRIPTION)) {
316 enforceRegisterSimSubscriptionPermission();
317 }
Ihab Awad8d5d9dd2015-03-12 11:11:06 -0700318 if (account.hasCapabilities(PhoneAccount.CAPABILITY_MULTI_USER)) {
319 enforceRegisterMultiUser();
320 }
321 enforceUserHandleMatchesCaller(account.getAccountHandle());
Santos Cordonf987d1a2014-12-02 03:37:03 -0800322
Ihab Awad8d5d9dd2015-03-12 11:11:06 -0700323 mPhoneAccountRegistrar.registerPhoneAccount(account);
Santos Cordon73853962015-02-27 15:13:35 -0800324
Ihab Awad8d5d9dd2015-03-12 11:11:06 -0700325 // Broadcast an intent indicating the phone account which was registered.
326 long token = Binder.clearCallingIdentity();
Yorke Lee58061752015-05-04 11:06:26 -0700327 try {
328 Intent intent = new Intent(TelecomManager.ACTION_PHONE_ACCOUNT_REGISTERED);
329 intent.putExtra(TelecomManager.EXTRA_PHONE_ACCOUNT_HANDLE,
330 account.getAccountHandle());
331 Log.i(this, "Sending phone-account intent as user");
332 mContext.sendBroadcastAsUser(intent, UserHandle.ALL,
333 PERMISSION_PROCESS_PHONE_ACCOUNT_REGISTRATION);
334 } finally {
335 Binder.restoreCallingIdentity(token);
336 }
Ihab Awad8d5d9dd2015-03-12 11:11:06 -0700337 } catch (Exception e) {
338 Log.e(this, e, "registerPhoneAccount %s", account);
339 throw e;
340 }
Santos Cordonf987d1a2014-12-02 03:37:03 -0800341 }
342 }
343
344 @Override
345 public void unregisterPhoneAccount(PhoneAccountHandle accountHandle) {
Ihab Awad8d5d9dd2015-03-12 11:11:06 -0700346 synchronized (mLock) {
347 try {
348 enforcePhoneAccountModificationForPackage(
349 accountHandle.getComponentName().getPackageName());
350 enforceUserHandleMatchesCaller(accountHandle);
351 mPhoneAccountRegistrar.unregisterPhoneAccount(accountHandle);
352 } catch (Exception e) {
353 Log.e(this, e, "unregisterPhoneAccount %s", accountHandle);
354 throw e;
355 }
Santos Cordonf987d1a2014-12-02 03:37:03 -0800356 }
357 }
358
359 @Override
360 public void clearAccounts(String packageName) {
Ihab Awad8d5d9dd2015-03-12 11:11:06 -0700361 synchronized (mLock) {
362 try {
363 enforcePhoneAccountModificationForPackage(packageName);
364 mPhoneAccountRegistrar
365 .clearAccounts(packageName, Binder.getCallingUserHandle());
366 } catch (Exception e) {
367 Log.e(this, e, "clearAccounts %s", packageName);
368 throw e;
369 }
Santos Cordonf987d1a2014-12-02 03:37:03 -0800370 }
371 }
372
373 /**
374 * @see android.telecom.TelecomManager#isVoiceMailNumber
375 */
376 @Override
Svet Ganov09611182015-04-16 12:29:01 -0700377 public boolean isVoiceMailNumber(PhoneAccountHandle accountHandle, String number,
378 String callingPackage) {
Ihab Awad8d5d9dd2015-03-12 11:11:06 -0700379 synchronized (mLock) {
Yorke Lee57138a62015-05-18 18:18:08 -0700380 if (!canReadPhoneState(callingPackage, "isVoiceMailNumber")) {
Svet Ganov09611182015-04-16 12:29:01 -0700381 return false;
382 }
383
Santos Cordonebf2d0f2015-05-15 10:28:29 -0700384 if (!isVisibleToCaller(accountHandle)) {
Santos Cordon3188b362015-05-22 13:01:10 -0700385 Log.w(this, "%s is not visible for the calling user [iVMN]", accountHandle);
Santos Cordonebf2d0f2015-05-15 10:28:29 -0700386 return false;
387 }
388
389 long token = Binder.clearCallingIdentity();
Ihab Awad8d5d9dd2015-03-12 11:11:06 -0700390 try {
Ihab Awad8d5d9dd2015-03-12 11:11:06 -0700391 return mPhoneAccountRegistrar.isVoiceMailNumber(accountHandle, number);
392 } catch (Exception e) {
393 Log.e(this, e, "getSubscriptionIdForPhoneAccount");
394 throw e;
Santos Cordonebf2d0f2015-05-15 10:28:29 -0700395 } finally {
396 Binder.restoreCallingIdentity(token);
Santos Cordonf987d1a2014-12-02 03:37:03 -0800397 }
Santos Cordonf987d1a2014-12-02 03:37:03 -0800398 }
399 }
400
401 /**
Yorke Leefb5ec302015-04-15 16:15:55 -0700402 * @see android.telecom.TelecomManager#getVoiceMailNumber
Santos Cordonf987d1a2014-12-02 03:37:03 -0800403 */
404 @Override
Svet Ganov09611182015-04-16 12:29:01 -0700405 public String getVoiceMailNumber(PhoneAccountHandle accountHandle, String callingPackage) {
Ihab Awad8d5d9dd2015-03-12 11:11:06 -0700406 synchronized (mLock) {
Yorke Lee57138a62015-05-18 18:18:08 -0700407 if (!canReadPhoneState(callingPackage, "getVoiceMailNumber")) {
Svet Ganov09611182015-04-16 12:29:01 -0700408 return null;
409 }
410
Ihab Awad8d5d9dd2015-03-12 11:11:06 -0700411 try {
412 if (!isVisibleToCaller(accountHandle)) {
Santos Cordon3188b362015-05-22 13:01:10 -0700413 Log.w(this, "%s is not visible for the calling user [gVMN]", accountHandle);
Yorke Leefb5ec302015-04-15 16:15:55 -0700414 return null;
Ihab Awad8d5d9dd2015-03-12 11:11:06 -0700415 }
Santos Cordonf987d1a2014-12-02 03:37:03 -0800416
Ihab Awad8d5d9dd2015-03-12 11:11:06 -0700417 int subId = SubscriptionManager.getDefaultVoiceSubId();
418 if (accountHandle != null) {
419 subId = mPhoneAccountRegistrar
420 .getSubscriptionIdForPhoneAccount(accountHandle);
421 }
Yorke Leefb5ec302015-04-15 16:15:55 -0700422 return getTelephonyManager().getVoiceMailNumber(subId);
Ihab Awad8d5d9dd2015-03-12 11:11:06 -0700423 } catch (Exception e) {
424 Log.e(this, e, "getSubscriptionIdForPhoneAccount");
425 throw e;
Ihab Awad78a5e6b2015-02-06 10:13:05 -0800426 }
Santos Cordonf987d1a2014-12-02 03:37:03 -0800427 }
428 }
429
430 /**
Nancy Chenba304752015-01-24 23:29:22 -0800431 * @see android.telecom.TelecomManager#getLine1Number
432 */
433 @Override
Svet Ganov09611182015-04-16 12:29:01 -0700434 public String getLine1Number(PhoneAccountHandle accountHandle, String callingPackage) {
Yorke Lee57138a62015-05-18 18:18:08 -0700435 if (!canReadPhoneState(callingPackage, "getLine1Number")) {
Svet Ganov09611182015-04-16 12:29:01 -0700436 return null;
437 }
438
Ihab Awad8d5d9dd2015-03-12 11:11:06 -0700439 synchronized (mLock) {
Santos Cordonebf2d0f2015-05-15 10:28:29 -0700440 if (!isVisibleToCaller(accountHandle)) {
Santos Cordon3188b362015-05-22 13:01:10 -0700441 Log.w(this, "%s is not visible for the calling user [gL1N]", accountHandle);
Santos Cordonebf2d0f2015-05-15 10:28:29 -0700442 return null;
443 }
444
445 long token = Binder.clearCallingIdentity();
Ihab Awad8d5d9dd2015-03-12 11:11:06 -0700446 try {
Ihab Awad8d5d9dd2015-03-12 11:11:06 -0700447 int subId =
448 mPhoneAccountRegistrar.getSubscriptionIdForPhoneAccount(accountHandle);
449 return getTelephonyManager().getLine1NumberForSubscriber(subId);
450 } catch (Exception e) {
451 Log.e(this, e, "getSubscriptionIdForPhoneAccount");
452 throw e;
Santos Cordonebf2d0f2015-05-15 10:28:29 -0700453 } finally {
454 Binder.restoreCallingIdentity(token);
Nancy Chenba304752015-01-24 23:29:22 -0800455 }
Nancy Chenba304752015-01-24 23:29:22 -0800456 }
457 }
458
459 /**
Santos Cordonf987d1a2014-12-02 03:37:03 -0800460 * @see android.telecom.TelecomManager#silenceRinger
461 */
462 @Override
Yorke Lee53101962015-04-29 16:25:29 -0700463 public void silenceRinger(String callingPackage) {
Ihab Awad8d5d9dd2015-03-12 11:11:06 -0700464 synchronized (mLock) {
Yorke Leecb0bd8a2015-05-18 11:57:14 -0700465 enforcePermissionOrPrivilegedDialer(MODIFY_PHONE_STATE, callingPackage);
Santos Cordonebf2d0f2015-05-15 10:28:29 -0700466
467 long token = Binder.clearCallingIdentity();
468 try {
Santos Cordona83f8a72015-06-02 17:12:39 -0700469 Log.i(this, "Silence Ringer requested by %s", callingPackage);
Santos Cordonebf2d0f2015-05-15 10:28:29 -0700470 mCallsManager.getRinger().silence();
471 } finally {
472 Binder.restoreCallingIdentity(token);
473 }
Ihab Awad8d5d9dd2015-03-12 11:11:06 -0700474 }
Santos Cordonf987d1a2014-12-02 03:37:03 -0800475 }
476
477 /**
478 * @see android.telecom.TelecomManager#getDefaultPhoneApp
Yorke Lee5b3fc0a2015-04-23 17:42:57 -0700479 * @deprecated - Use {@link android.telecom.TelecomManager#getDefaultDialerPackage()}
480 * instead.
Santos Cordonf987d1a2014-12-02 03:37:03 -0800481 */
482 @Override
483 public ComponentName getDefaultPhoneApp() {
Ihab Awad8d5d9dd2015-03-12 11:11:06 -0700484 // No need to synchronize
Santos Cordonf987d1a2014-12-02 03:37:03 -0800485 Resources resources = mContext.getResources();
486 return new ComponentName(
487 resources.getString(R.string.ui_default_package),
488 resources.getString(R.string.dialer_default_class));
489 }
490
491 /**
Yorke Lee5291d4a2015-04-24 16:42:36 -0700492 * @return the package name of the current user-selected default dialer. If no default
493 * has been selected, the package name of the system dialer is returned. If
494 * neither exists, then {@code null} is returned.
Yorke Lee5b3fc0a2015-04-23 17:42:57 -0700495 * @see android.telecom.TelecomManager#getDefaultDialerPackage
496 */
497 @Override
498 public String getDefaultDialerPackage() {
Yorke Lee29c003e2015-05-04 17:09:27 -0700499 final long token = Binder.clearCallingIdentity();
500 try {
501 return DefaultDialerManager.getDefaultDialerApplication(mContext);
502 } finally {
503 Binder.restoreCallingIdentity(token);
504 }
Yorke Lee5b3fc0a2015-04-23 17:42:57 -0700505 }
506
507 /**
508 * @see android.telecom.TelecomManager#getSystemDialerPackage
509 */
510 @Override
511 public String getSystemDialerPackage() {
512 return mContext.getResources().getString(R.string.ui_default_package);
513 }
514
515 /**
Santos Cordonf987d1a2014-12-02 03:37:03 -0800516 * @see android.telecom.TelecomManager#isInCall
517 */
518 @Override
Svet Ganov09611182015-04-16 12:29:01 -0700519 public boolean isInCall(String callingPackage) {
Svet Ganov38f1a4d2015-04-17 15:28:03 -0700520 if (!canReadPhoneState(callingPackage, "isInCall")) {
521 return false;
Svet Ganov09611182015-04-16 12:29:01 -0700522 }
523
Ihab Awad8d5d9dd2015-03-12 11:11:06 -0700524 synchronized (mLock) {
Ihab Awad8d5d9dd2015-03-12 11:11:06 -0700525 final int callState = mCallsManager.getCallState();
526 return callState == TelephonyManager.CALL_STATE_OFFHOOK
527 || callState == TelephonyManager.CALL_STATE_RINGING;
528 }
Santos Cordonf987d1a2014-12-02 03:37:03 -0800529 }
530
531 /**
532 * @see android.telecom.TelecomManager#isRinging
533 */
534 @Override
Svet Ganov09611182015-04-16 12:29:01 -0700535 public boolean isRinging(String callingPackage) {
Svet Ganov38f1a4d2015-04-17 15:28:03 -0700536 if (!canReadPhoneState(callingPackage, "isRinging")) {
537 return false;
Svet Ganov09611182015-04-16 12:29:01 -0700538 }
539
Ihab Awad8d5d9dd2015-03-12 11:11:06 -0700540 synchronized (mLock) {
Ihab Awad8d5d9dd2015-03-12 11:11:06 -0700541 return mCallsManager.getCallState() == TelephonyManager.CALL_STATE_RINGING;
542 }
Santos Cordonf987d1a2014-12-02 03:37:03 -0800543 }
544
545 /**
546 * @see TelecomManager#getCallState
547 */
548 @Override
549 public int getCallState() {
Ihab Awad8d5d9dd2015-03-12 11:11:06 -0700550 synchronized (mLock) {
551 return mCallsManager.getCallState();
552 }
Santos Cordonf987d1a2014-12-02 03:37:03 -0800553 }
554
555 /**
556 * @see android.telecom.TelecomManager#endCall
557 */
558 @Override
559 public boolean endCall() {
Ihab Awad8d5d9dd2015-03-12 11:11:06 -0700560 synchronized (mLock) {
561 enforceModifyPermission();
Santos Cordonebf2d0f2015-05-15 10:28:29 -0700562
563 long token = Binder.clearCallingIdentity();
564 try {
565 return endCallInternal();
566 } finally {
567 Binder.restoreCallingIdentity(token);
568 }
Ihab Awad8d5d9dd2015-03-12 11:11:06 -0700569 }
Santos Cordonf987d1a2014-12-02 03:37:03 -0800570 }
571
572 /**
573 * @see android.telecom.TelecomManager#acceptRingingCall
574 */
575 @Override
576 public void acceptRingingCall() {
Ihab Awad8d5d9dd2015-03-12 11:11:06 -0700577 synchronized (mLock) {
578 enforceModifyPermission();
Santos Cordonebf2d0f2015-05-15 10:28:29 -0700579
580 long token = Binder.clearCallingIdentity();
581 try {
582 acceptRingingCallInternal();
583 } finally {
584 Binder.restoreCallingIdentity(token);
585 }
Ihab Awad8d5d9dd2015-03-12 11:11:06 -0700586 }
Santos Cordonf987d1a2014-12-02 03:37:03 -0800587 }
588
589 /**
590 * @see android.telecom.TelecomManager#showInCallScreen
591 */
592 @Override
Svet Ganov09611182015-04-16 12:29:01 -0700593 public void showInCallScreen(boolean showDialpad, String callingPackage) {
Yorke Lee57138a62015-05-18 18:18:08 -0700594 if (!canReadPhoneState(callingPackage, "showInCallScreen")) {
Svet Ganov09611182015-04-16 12:29:01 -0700595 return;
596 }
597
Ihab Awad8d5d9dd2015-03-12 11:11:06 -0700598 synchronized (mLock) {
Santos Cordonebf2d0f2015-05-15 10:28:29 -0700599
600 long token = Binder.clearCallingIdentity();
601 try {
602 mCallsManager.getInCallController().bringToForeground(showDialpad);
603 } finally {
604 Binder.restoreCallingIdentity(token);
605 }
Ihab Awad8d5d9dd2015-03-12 11:11:06 -0700606 }
Santos Cordonf987d1a2014-12-02 03:37:03 -0800607 }
608
609 /**
610 * @see android.telecom.TelecomManager#cancelMissedCallsNotification
611 */
612 @Override
Yorke Lee53101962015-04-29 16:25:29 -0700613 public void cancelMissedCallsNotification(String callingPackage) {
Ihab Awad8d5d9dd2015-03-12 11:11:06 -0700614 synchronized (mLock) {
Yorke Leecb0bd8a2015-05-18 11:57:14 -0700615 enforcePermissionOrPrivilegedDialer(MODIFY_PHONE_STATE, callingPackage);
Santos Cordonebf2d0f2015-05-15 10:28:29 -0700616 long token = Binder.clearCallingIdentity();
617 try {
618 mCallsManager.getMissedCallNotifier().clearMissedCalls();
619 } finally {
620 Binder.restoreCallingIdentity(token);
621 }
Ihab Awad8d5d9dd2015-03-12 11:11:06 -0700622 }
Santos Cordonf987d1a2014-12-02 03:37:03 -0800623 }
624
625 /**
626 * @see android.telecom.TelecomManager#handleMmi
627 */
628 @Override
Yorke Lee53101962015-04-29 16:25:29 -0700629 public boolean handlePinMmi(String dialString, String callingPackage) {
Ihab Awad8d5d9dd2015-03-12 11:11:06 -0700630 synchronized (mLock) {
Yorke Leecb0bd8a2015-05-18 11:57:14 -0700631 enforcePermissionOrPrivilegedDialer(MODIFY_PHONE_STATE, callingPackage);
Santos Cordonf987d1a2014-12-02 03:37:03 -0800632
Ihab Awad8d5d9dd2015-03-12 11:11:06 -0700633 // Switch identity so that TelephonyManager checks Telecom's permissions instead.
634 long token = Binder.clearCallingIdentity();
635 boolean retval = false;
636 try {
637 retval = getTelephonyManager().handlePinMmi(dialString);
638 } finally {
639 Binder.restoreCallingIdentity(token);
640 }
641
642 return retval;
Santos Cordonf987d1a2014-12-02 03:37:03 -0800643 }
Santos Cordonf987d1a2014-12-02 03:37:03 -0800644 }
645
646 /**
647 * @see android.telecom.TelecomManager#handleMmi
648 */
649 @Override
Ihab Awad8d5d9dd2015-03-12 11:11:06 -0700650 public boolean handlePinMmiForPhoneAccount(
651 PhoneAccountHandle accountHandle,
Yorke Lee53101962015-04-29 16:25:29 -0700652 String dialString,
653 String callingPackage) {
Ihab Awad8d5d9dd2015-03-12 11:11:06 -0700654 synchronized (mLock) {
Yorke Leecb0bd8a2015-05-18 11:57:14 -0700655 enforcePermissionOrPrivilegedDialer(MODIFY_PHONE_STATE, callingPackage);
Santos Cordonf987d1a2014-12-02 03:37:03 -0800656
Ihab Awad8d5d9dd2015-03-12 11:11:06 -0700657 if (!isVisibleToCaller(accountHandle)) {
Santos Cordon3188b362015-05-22 13:01:10 -0700658 Log.w(this, "%s is not visible for the calling user [hMMI]", accountHandle);
Ihab Awad8d5d9dd2015-03-12 11:11:06 -0700659 return false;
660 }
661
662 // Switch identity so that TelephonyManager checks Telecom's permissions instead.
663 long token = Binder.clearCallingIdentity();
664 boolean retval = false;
665 try {
666 int subId = mPhoneAccountRegistrar
667 .getSubscriptionIdForPhoneAccount(accountHandle);
668 retval = getTelephonyManager().handlePinMmiForSubscriber(subId, dialString);
669 } finally {
670 Binder.restoreCallingIdentity(token);
671 }
672
673 return retval;
Santos Cordonf987d1a2014-12-02 03:37:03 -0800674 }
Santos Cordonf987d1a2014-12-02 03:37:03 -0800675 }
676
677 /**
678 * @see android.telecom.TelecomManager#getAdnUriForPhoneAccount
679 */
680 @Override
Yorke Lee53101962015-04-29 16:25:29 -0700681 public Uri getAdnUriForPhoneAccount(PhoneAccountHandle accountHandle,
682 String callingPackage) {
Ihab Awad8d5d9dd2015-03-12 11:11:06 -0700683 synchronized (mLock) {
Yorke Leecb0bd8a2015-05-18 11:57:14 -0700684 enforcePermissionOrPrivilegedDialer(MODIFY_PHONE_STATE, callingPackage);
Santos Cordonf987d1a2014-12-02 03:37:03 -0800685
Ihab Awad8d5d9dd2015-03-12 11:11:06 -0700686 if (!isVisibleToCaller(accountHandle)) {
Santos Cordon3188b362015-05-22 13:01:10 -0700687 Log.w(this, "%s is not visible for the calling user [gA4PA]", accountHandle);
Ihab Awad8d5d9dd2015-03-12 11:11:06 -0700688 return null;
689 }
690
691 // Switch identity so that TelephonyManager checks Telecom's permissions instead.
692 long token = Binder.clearCallingIdentity();
693 String retval = "content://icc/adn/";
694 try {
695 long subId = mPhoneAccountRegistrar
696 .getSubscriptionIdForPhoneAccount(accountHandle);
697 retval = retval + "subId/" + subId;
698 } finally {
699 Binder.restoreCallingIdentity(token);
700 }
701
702 return Uri.parse(retval);
Santos Cordonf987d1a2014-12-02 03:37:03 -0800703 }
Santos Cordonf987d1a2014-12-02 03:37:03 -0800704 }
705
706 /**
707 * @see android.telecom.TelecomManager#isTtySupported
708 */
709 @Override
Svet Ganov09611182015-04-16 12:29:01 -0700710 public boolean isTtySupported(String callingPackage) {
Svet Ganov38f1a4d2015-04-17 15:28:03 -0700711 if (!canReadPhoneState(callingPackage, "hasVoiceMailNumber")) {
712 return false;
Svet Ganov09611182015-04-16 12:29:01 -0700713 }
714
Ihab Awad8d5d9dd2015-03-12 11:11:06 -0700715 synchronized (mLock) {
Ihab Awad8d5d9dd2015-03-12 11:11:06 -0700716 return mCallsManager.isTtySupported();
717 }
Santos Cordonf987d1a2014-12-02 03:37:03 -0800718 }
719
720 /**
721 * @see android.telecom.TelecomManager#getCurrentTtyMode
722 */
723 @Override
Svet Ganov09611182015-04-16 12:29:01 -0700724 public int getCurrentTtyMode(String callingPackage) {
Svet Ganov38f1a4d2015-04-17 15:28:03 -0700725 if (!canReadPhoneState(callingPackage, "getCurrentTtyMode")) {
Svet Ganov09611182015-04-16 12:29:01 -0700726 return TelecomManager.TTY_MODE_OFF;
727 }
728
Ihab Awad8d5d9dd2015-03-12 11:11:06 -0700729 synchronized (mLock) {
Ihab Awad8d5d9dd2015-03-12 11:11:06 -0700730 return mCallsManager.getCurrentTtyMode();
731 }
Santos Cordonf987d1a2014-12-02 03:37:03 -0800732 }
733
734 /**
735 * @see android.telecom.TelecomManager#addNewIncomingCall
736 */
737 @Override
738 public void addNewIncomingCall(PhoneAccountHandle phoneAccountHandle, Bundle extras) {
Ihab Awad8d5d9dd2015-03-12 11:11:06 -0700739 synchronized (mLock) {
740 Log.i(this, "Adding new incoming call with phoneAccountHandle %s",
741 phoneAccountHandle);
742 if (phoneAccountHandle != null && phoneAccountHandle.getComponentName() != null) {
743 mAppOpsManager.checkPackage(
744 Binder.getCallingUid(),
Sailesh Nepal2a98c972015-03-04 15:43:15 -0800745 phoneAccountHandle.getComponentName().getPackageName());
Ihab Awad8d5d9dd2015-03-12 11:11:06 -0700746
Sailesh Nepal2a98c972015-03-04 15:43:15 -0800747 // Make sure it doesn't cross the UserHandle boundary
748 enforceUserHandleMatchesCaller(phoneAccountHandle);
Sharvil Nanavati6d3efb42015-05-14 11:36:40 -0700749 long token = Binder.clearCallingIdentity();
Santos Cordonf987d1a2014-12-02 03:37:03 -0800750
Sharvil Nanavati6d3efb42015-05-14 11:36:40 -0700751 try {
752 Intent intent = new Intent(TelecomManager.ACTION_INCOMING_CALL);
753 intent.putExtra(TelecomManager.EXTRA_PHONE_ACCOUNT_HANDLE,
754 phoneAccountHandle);
755 intent.putExtra(CallIntentProcessor.KEY_IS_INCOMING_CALL, true);
756 if (extras != null) {
757 intent.putExtra(TelecomManager.EXTRA_INCOMING_CALL_EXTRAS, extras);
758 }
759 CallIntentProcessor.processIncomingCallIntent(mCallsManager, intent);
760 } finally {
761 Binder.restoreCallingIdentity(token);
Ihab Awad8d5d9dd2015-03-12 11:11:06 -0700762 }
Ihab Awad8d5d9dd2015-03-12 11:11:06 -0700763 } else {
764 Log.w(this,
765 "Null phoneAccountHandle. Ignoring request to add new incoming call");
Santos Cordonf987d1a2014-12-02 03:37:03 -0800766 }
Santos Cordonf987d1a2014-12-02 03:37:03 -0800767 }
768 }
769
770 /**
771 * @see android.telecom.TelecomManager#addNewUnknownCall
772 */
773 @Override
774 public void addNewUnknownCall(PhoneAccountHandle phoneAccountHandle, Bundle extras) {
Ihab Awad8d5d9dd2015-03-12 11:11:06 -0700775 synchronized (mLock) {
David Stevens07852742015-04-10 18:22:47 -0700776 if (phoneAccountHandle != null && phoneAccountHandle.getComponentName() != null) {
Ihab Awad8d5d9dd2015-03-12 11:11:06 -0700777 mAppOpsManager.checkPackage(
778 Binder.getCallingUid(),
779 phoneAccountHandle.getComponentName().getPackageName());
Santos Cordonf987d1a2014-12-02 03:37:03 -0800780
Ihab Awad8d5d9dd2015-03-12 11:11:06 -0700781 // Make sure it doesn't cross the UserHandle boundary
782 enforceUserHandleMatchesCaller(phoneAccountHandle);
Sharvil Nanavati6d3efb42015-05-14 11:36:40 -0700783 long token = Binder.clearCallingIdentity();
Santos Cordonf987d1a2014-12-02 03:37:03 -0800784
Sharvil Nanavati6d3efb42015-05-14 11:36:40 -0700785 try {
786 Intent intent = new Intent(TelecomManager.ACTION_NEW_UNKNOWN_CALL);
787 intent.putExtras(extras);
788 intent.putExtra(CallIntentProcessor.KEY_IS_UNKNOWN_CALL, true);
789 intent.putExtra(TelecomManager.EXTRA_PHONE_ACCOUNT_HANDLE,
790 phoneAccountHandle);
791 CallIntentProcessor.processUnknownCallIntent(mCallsManager, intent);
792 } finally {
793 Binder.restoreCallingIdentity(token);
794 }
Ihab Awad8d5d9dd2015-03-12 11:11:06 -0700795 } else {
796 Log.i(this,
797 "Null phoneAccountHandle or not initiated by Telephony. " +
798 "Ignoring request to add new unknown call.");
799 }
Santos Cordonf987d1a2014-12-02 03:37:03 -0800800 }
801 }
Tyler Gunn47689862014-12-17 17:10:28 -0800802
803 /**
Yorke Leea3a3adc2015-04-23 12:49:01 -0700804 * @see android.telecom.TelecomManager#placeCall
805 */
806 @Override
807 public void placeCall(Uri handle, Bundle extras, String callingPackage) {
808 enforceCallingPackage(callingPackage);
Yorke Lee57138a62015-05-18 18:18:08 -0700809 if (!canCallPhone(callingPackage, "placeCall")) {
810 throw new SecurityException("Package " + callingPackage
811 + " is not allowed to place phone calls");
812 }
Yorke Leecb0bd8a2015-05-18 11:57:14 -0700813
Yorke Leea3a3adc2015-04-23 12:49:01 -0700814 synchronized (mLock) {
Yorke Leeb3feab52015-04-30 12:35:16 -0700815 final UserHandle userHandle = Binder.getCallingUserHandle();
Yorke Leeb7910662015-04-24 12:00:19 -0700816 long token = Binder.clearCallingIdentity();
Yorke Lee58061752015-05-04 11:06:26 -0700817 try {
818 final Intent intent = new Intent(Intent.ACTION_CALL, handle);
819 intent.putExtras(extras);
820 new UserCallIntentProcessor(mContext, userHandle).processIntent(intent,
821 callingPackage);
822 } finally {
823 Binder.restoreCallingIdentity(token);
824 }
Yorke Leea3a3adc2015-04-23 12:49:01 -0700825 }
826 }
827
828 /**
Santos Cordonea5cb932015-05-07 16:28:38 -0700829 * @see android.telecom.TelecomManager#enablePhoneAccount
830 */
831 @Override
Yorke Lee71734c22015-06-02 14:22:56 -0700832 public boolean enablePhoneAccount(PhoneAccountHandle accountHandle, boolean isEnabled) {
Santos Cordonea5cb932015-05-07 16:28:38 -0700833 enforceModifyPermission();
834 synchronized (mLock) {
835 long token = Binder.clearCallingIdentity();
836 try {
837 // enable/disable phone account
Yorke Lee71734c22015-06-02 14:22:56 -0700838 return mPhoneAccountRegistrar.enablePhoneAccount(accountHandle, isEnabled);
839 } finally {
840 Binder.restoreCallingIdentity(token);
841 }
842 }
843 }
844
845 @Override
846 public boolean setDefaultDialer(String packageName) {
847 enforcePermission(MODIFY_PHONE_STATE);
848 enforcePermission(WRITE_SECURE_SETTINGS);
849 synchronized (mLock) {
850 long token = Binder.clearCallingIdentity();
851 try {
852 return DefaultDialerManager.setDefaultDialerApplication(mContext, packageName);
Santos Cordonea5cb932015-05-07 16:28:38 -0700853 } finally {
854 Binder.restoreCallingIdentity(token);
855 }
856 }
857 }
858
859 /**
Tyler Gunn47689862014-12-17 17:10:28 -0800860 * Dumps the current state of the TelecomService. Used when generating problem reports.
861 *
862 * @param fd The file descriptor.
863 * @param writer The print writer to dump the state to.
864 * @param args Optional dump arguments.
865 */
866 @Override
867 protected void dump(FileDescriptor fd, final PrintWriter writer, String[] args) {
868 if (mContext.checkCallingOrSelfPermission(
869 android.Manifest.permission.DUMP)
870 != PackageManager.PERMISSION_GRANTED) {
871 writer.println("Permission Denial: can't dump TelecomService " +
872 "from from pid=" + Binder.getCallingPid() + ", uid=" +
873 Binder.getCallingUid());
874 return;
875 }
876
877 final IndentingPrintWriter pw = new IndentingPrintWriter(writer, " ");
Ihab Awad8de76912015-02-17 12:25:52 -0800878 if (mCallsManager != null) {
Ihab Awad78a5e6b2015-02-06 10:13:05 -0800879 pw.println("CallsManager: ");
Tyler Gunn47689862014-12-17 17:10:28 -0800880 pw.increaseIndent();
Ihab Awad8de76912015-02-17 12:25:52 -0800881 mCallsManager.dump(pw);
Tyler Gunn47689862014-12-17 17:10:28 -0800882 pw.decreaseIndent();
883
Ihab Awad78a5e6b2015-02-06 10:13:05 -0800884 pw.println("PhoneAccountRegistrar: ");
Tyler Gunn47689862014-12-17 17:10:28 -0800885 pw.increaseIndent();
Ihab Awad8d5d9dd2015-03-12 11:11:06 -0700886 mPhoneAccountRegistrar.dump(pw);
Tyler Gunn47689862014-12-17 17:10:28 -0800887 pw.decreaseIndent();
888 }
Santos Cordon2685dab2015-04-17 17:12:09 -0700889
890 Log.dumpCallEvents(pw);
Tyler Gunn47689862014-12-17 17:10:28 -0800891 }
Ihab Awad8d5d9dd2015-03-12 11:11:06 -0700892 };
893
894 private Context mContext;
895 private AppOpsManager mAppOpsManager;
896 private UserManager mUserManager;
897 private PackageManager mPackageManager;
898 private CallsManager mCallsManager;
899 private final PhoneAccountRegistrar mPhoneAccountRegistrar;
900 private final TelecomSystem.SyncRoot mLock;
901
902 public TelecomServiceImpl(
903 Context context,
904 CallsManager callsManager,
905 PhoneAccountRegistrar phoneAccountRegistrar,
906 TelecomSystem.SyncRoot lock) {
907 mContext = context;
908 mAppOpsManager = (AppOpsManager) mContext.getSystemService(Context.APP_OPS_SERVICE);
909
910 mUserManager = (UserManager) mContext.getSystemService(Context.USER_SERVICE);
911 mPackageManager = mContext.getPackageManager();
912
913 mCallsManager = callsManager;
914 mLock = lock;
915 mPhoneAccountRegistrar = phoneAccountRegistrar;
916 }
917
Ihab Awadaa383cc2015-03-22 22:12:28 -0700918 public ITelecomService.Stub getBinder() {
Ihab Awad8d5d9dd2015-03-12 11:11:06 -0700919 return mBinderImpl;
Santos Cordonf987d1a2014-12-02 03:37:03 -0800920 }
921
922 //
923 // Supporting methods for the ITelecomService interface implementation.
924 //
925
926 private boolean isVisibleToCaller(PhoneAccountHandle accountHandle) {
927 if (accountHandle == null) {
928 return false;
929 }
Santos Cordon6a212642015-05-08 16:35:23 -0700930 return isVisibleToCaller(mPhoneAccountRegistrar.getPhoneAccount(accountHandle));
Santos Cordonf987d1a2014-12-02 03:37:03 -0800931 }
932
933 private boolean isVisibleToCaller(PhoneAccount account) {
934 if (account == null) {
935 return false;
936 }
937
938 // If this PhoneAccount has CAPABILITY_MULTI_USER, it should be visible to all users and
939 // all profiles. Only Telephony and SIP accounts should have this capability.
940 if (account.hasCapabilities(PhoneAccount.CAPABILITY_MULTI_USER)) {
941 return true;
942 }
943
944 UserHandle phoneAccountUserHandle = account.getAccountHandle().getUserHandle();
945 if (phoneAccountUserHandle == null) {
946 return false;
947 }
948
Sailesh Nepal91fc8092015-02-14 15:44:55 -0800949 if (phoneAccountUserHandle.equals(Binder.getCallingUserHandle())) {
950 return true;
951 }
952
Santos Cordonf987d1a2014-12-02 03:37:03 -0800953 List<UserHandle> profileUserHandles;
Sailesh Nepal91fc8092015-02-14 15:44:55 -0800954 if (UserHandle.getCallingUserId() == UserHandle.USER_OWNER) {
Santos Cordonf987d1a2014-12-02 03:37:03 -0800955 profileUserHandles = mUserManager.getUserProfiles();
956 } else {
957 // Otherwise, it has to be owned by the current caller's profile.
958 profileUserHandles = new ArrayList<>(1);
959 profileUserHandles.add(Binder.getCallingUserHandle());
960 }
961
962 return profileUserHandles.contains(phoneAccountUserHandle);
963 }
964
965 /**
966 * Given a list of {@link PhoneAccountHandle}s, filter them to the ones that the calling
967 * user can see.
968 *
969 * @param phoneAccountHandles Unfiltered list of account handles.
970 *
971 * @return {@link PhoneAccountHandle}s visible to the calling user and its profiles.
972 */
973 private List<PhoneAccountHandle> filterForAccountsVisibleToCaller(
974 List<PhoneAccountHandle> phoneAccountHandles) {
975 List<PhoneAccountHandle> profilePhoneAccountHandles =
976 new ArrayList<>(phoneAccountHandles.size());
977 for (PhoneAccountHandle phoneAccountHandle : phoneAccountHandles) {
978 if (isVisibleToCaller(phoneAccountHandle)) {
979 profilePhoneAccountHandles.add(phoneAccountHandle);
980 }
981 }
982 return profilePhoneAccountHandles;
983 }
984
985 private boolean isCallerSystemApp() {
986 int uid = Binder.getCallingUid();
987 String[] packages = mPackageManager.getPackagesForUid(uid);
988 for (String packageName : packages) {
989 if (isPackageSystemApp(packageName)) {
990 return true;
991 }
992 }
993 return false;
994 }
995
996 private boolean isPackageSystemApp(String packageName) {
997 try {
998 ApplicationInfo applicationInfo = mPackageManager.getApplicationInfo(packageName,
999 PackageManager.GET_META_DATA);
1000 if ((applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0) {
1001 return true;
1002 }
1003 } catch (PackageManager.NameNotFoundException e) {
1004 }
1005 return false;
1006 }
1007
1008 private void acceptRingingCallInternal() {
Ihab Awad8de76912015-02-17 12:25:52 -08001009 Call call = mCallsManager.getFirstCallWithState(CallState.RINGING);
Santos Cordonf987d1a2014-12-02 03:37:03 -08001010 if (call != null) {
1011 call.answer(call.getVideoState());
1012 }
1013 }
1014
1015 private boolean endCallInternal() {
1016 // Always operate on the foreground call if one exists, otherwise get the first call in
1017 // priority order by call-state.
Ihab Awad8de76912015-02-17 12:25:52 -08001018 Call call = mCallsManager.getForegroundCall();
Santos Cordonf987d1a2014-12-02 03:37:03 -08001019 if (call == null) {
Ihab Awad8de76912015-02-17 12:25:52 -08001020 call = mCallsManager.getFirstCallWithState(
Santos Cordonf987d1a2014-12-02 03:37:03 -08001021 CallState.ACTIVE,
1022 CallState.DIALING,
1023 CallState.RINGING,
1024 CallState.ON_HOLD);
1025 }
1026
1027 if (call != null) {
1028 if (call.getState() == CallState.RINGING) {
1029 call.reject(false /* rejectWithMessage */, null);
1030 } else {
1031 call.disconnect();
1032 }
1033 return true;
1034 }
1035
1036 return false;
1037 }
1038
1039 private void enforcePhoneAccountModificationForPackage(String packageName) {
1040 // TODO: Use a new telecomm permission for this instead of reusing modify.
1041
Yorke Leecb0bd8a2015-05-18 11:57:14 -07001042 int result = mContext.checkCallingOrSelfPermission(MODIFY_PHONE_STATE);
Santos Cordonf987d1a2014-12-02 03:37:03 -08001043
1044 // Callers with MODIFY_PHONE_STATE can use the PhoneAccount mechanism to implement
1045 // built-in behavior even when PhoneAccounts are not exposed as a third-part API. They
1046 // may also modify PhoneAccounts on behalf of any 'packageName'.
1047
1048 if (result != PackageManager.PERMISSION_GRANTED) {
1049 // Other callers are only allowed to modify PhoneAccounts if the relevant system
1050 // feature is enabled ...
1051 enforceConnectionServiceFeature();
1052 // ... and the PhoneAccounts they refer to are for their own package.
1053 enforceCallingPackage(packageName);
1054 }
1055 }
1056
Yorke Leecb0bd8a2015-05-18 11:57:14 -07001057 private void enforcePermissionOrPrivilegedDialer(String permission, String packageName) {
Yorke Lee53101962015-04-29 16:25:29 -07001058 if (!isPrivilegedDialerCalling(packageName)) {
1059 try {
Yorke Leecb0bd8a2015-05-18 11:57:14 -07001060 enforcePermission(permission);
Yorke Lee53101962015-04-29 16:25:29 -07001061 } catch (SecurityException e) {
Yorke Leecb0bd8a2015-05-18 11:57:14 -07001062 Log.e(this, e, "Caller must be the default or system dialer, or have the permission"
1063 + " %s to perform this operation.", permission);
Yorke Lee53101962015-04-29 16:25:29 -07001064 throw e;
1065 }
Santos Cordonf987d1a2014-12-02 03:37:03 -08001066 }
1067 }
1068
1069 private void enforceCallingPackage(String packageName) {
1070 mAppOpsManager.checkPackage(Binder.getCallingUid(), packageName);
1071 }
1072
1073 private void enforceConnectionServiceFeature() {
1074 enforceFeature(PackageManager.FEATURE_CONNECTION_SERVICE);
1075 }
1076
1077 private void enforceRegisterCallProviderPermission() {
Yorke Leecb0bd8a2015-05-18 11:57:14 -07001078 enforcePermission(REGISTER_CALL_PROVIDER);
Santos Cordonf987d1a2014-12-02 03:37:03 -08001079 }
1080
1081 private void enforceRegisterSimSubscriptionPermission() {
Yorke Leecb0bd8a2015-05-18 11:57:14 -07001082 enforcePermission(REGISTER_SIM_SUBSCRIPTION);
Santos Cordonf987d1a2014-12-02 03:37:03 -08001083 }
1084
1085 private void enforceRegisterConnectionManagerPermission() {
Yorke Leecb0bd8a2015-05-18 11:57:14 -07001086 enforcePermission(REGISTER_CONNECTION_MANAGER);
Santos Cordonf987d1a2014-12-02 03:37:03 -08001087 }
1088
Santos Cordonf987d1a2014-12-02 03:37:03 -08001089 private void enforceModifyPermission() {
Yorke Leecb0bd8a2015-05-18 11:57:14 -07001090 enforcePermission(MODIFY_PHONE_STATE);
Santos Cordonf987d1a2014-12-02 03:37:03 -08001091 }
1092
1093 private void enforcePermission(String permission) {
1094 mContext.enforceCallingOrSelfPermission(permission, null);
1095 }
1096
1097 private void enforceRegisterMultiUser() {
1098 if (!isCallerSystemApp()) {
1099 throw new SecurityException("CAPABILITY_MULTI_USER is only available to system apps.");
1100 }
1101 }
1102
1103 private void enforceUserHandleMatchesCaller(PhoneAccountHandle accountHandle) {
1104 if (!Binder.getCallingUserHandle().equals(accountHandle.getUserHandle())) {
1105 throw new SecurityException("Calling UserHandle does not match PhoneAccountHandle's");
1106 }
1107 }
1108
1109 private void enforceFeature(String feature) {
1110 PackageManager pm = mContext.getPackageManager();
1111 if (!pm.hasSystemFeature(feature)) {
1112 throw new UnsupportedOperationException(
1113 "System does not support feature " + feature);
1114 }
1115 }
1116
Svet Ganov38f1a4d2015-04-17 15:28:03 -07001117 private boolean canReadPhoneState(String callingPackage, String message) {
Yorke Lee57138a62015-05-18 18:18:08 -07001118 // The system/default dialer can always read phone state - so that emergency calls will
1119 // still work.
1120 if (isPrivilegedDialerCalling(callingPackage)) {
1121 return true;
1122 }
1123
Svet Ganov09611182015-04-16 12:29:01 -07001124 // Accessing phone state is gated by a special permission.
Yorke Leecb0bd8a2015-05-18 11:57:14 -07001125 mContext.enforceCallingOrSelfPermission(READ_PHONE_STATE, message);
Svet Ganov09611182015-04-16 12:29:01 -07001126
1127 // Some apps that have the permission can be restricted via app ops.
1128 return mAppOpsManager.noteOp(AppOpsManager.OP_READ_PHONE_STATE,
1129 Binder.getCallingUid(), callingPackage) == AppOpsManager.MODE_ALLOWED;
1130 }
1131
Yorke Leea3a3adc2015-04-23 12:49:01 -07001132 private boolean canCallPhone(String callingPackage, String message) {
Yorke Lee57138a62015-05-18 18:18:08 -07001133 // The system/default dialer can always read phone state - so that emergency calls will
1134 // still work.
1135 if (isPrivilegedDialerCalling(callingPackage)) {
1136 return true;
1137 }
1138
Yorke Leea3a3adc2015-04-23 12:49:01 -07001139 // Accessing phone state is gated by a special permission.
Yorke Leecb0bd8a2015-05-18 11:57:14 -07001140 mContext.enforceCallingOrSelfPermission(CALL_PHONE, message);
Yorke Leea3a3adc2015-04-23 12:49:01 -07001141
1142 // Some apps that have the permission can be restricted via app ops.
1143 return mAppOpsManager.noteOp(AppOpsManager.OP_CALL_PHONE,
1144 Binder.getCallingUid(), callingPackage) == AppOpsManager.MODE_ALLOWED;
1145 }
1146
Sailesh Nepal2a98c972015-03-04 15:43:15 -08001147 private boolean isCallerSimCallManager() {
Etan Cohenb600a5f2015-03-06 17:37:30 -08001148 PhoneAccountHandle accountHandle = TelecomSystem.getInstance().getPhoneAccountRegistrar()
1149 .getSimCallManager();
Sailesh Nepal2a98c972015-03-04 15:43:15 -08001150 if (accountHandle != null) {
1151 try {
1152 mAppOpsManager.checkPackage(
1153 Binder.getCallingUid(), accountHandle.getComponentName().getPackageName());
1154 return true;
1155 } catch (SecurityException e) {
1156 }
1157 }
1158 return false;
1159 }
1160
Yorke Lee53101962015-04-29 16:25:29 -07001161 private boolean isPrivilegedDialerCalling(String callingPackage) {
1162 mAppOpsManager.checkPackage(Binder.getCallingUid(), callingPackage);
1163 return DefaultDialerManager.isDefaultOrSystemDialer(mContext, callingPackage);
Santos Cordonf987d1a2014-12-02 03:37:03 -08001164 }
1165
1166 private TelephonyManager getTelephonyManager() {
1167 return (TelephonyManager)mContext.getSystemService(Context.TELEPHONY_SERVICE);
1168 }
Santos Cordonf987d1a2014-12-02 03:37:03 -08001169}