blob: a07cd87bbb01ee0c7523a18c6d11f3a4219b7067 [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
Yorke Leeb3984302015-06-15 12:06:35 -070027import android.app.ActivityManager;
Santos Cordonf987d1a2014-12-02 03:37:03 -080028import android.app.AppOpsManager;
Santos Cordonf987d1a2014-12-02 03:37:03 -080029import android.content.ComponentName;
30import android.content.Context;
31import android.content.Intent;
32import android.content.pm.ApplicationInfo;
33import android.content.pm.PackageManager;
34import android.content.res.Resources;
35import android.net.Uri;
36import android.os.Binder;
37import android.os.Bundle;
Santos Cordonf987d1a2014-12-02 03:37:03 -080038import android.os.IBinder;
Santos Cordonf987d1a2014-12-02 03:37:03 -080039import android.os.UserHandle;
40import android.os.UserManager;
Yorke Lee5b3fc0a2015-04-23 17:42:57 -070041import android.telecom.DefaultDialerManager;
Santos Cordonf987d1a2014-12-02 03:37:03 -080042import android.telecom.PhoneAccount;
43import android.telecom.PhoneAccountHandle;
44import android.telecom.TelecomManager;
45import android.telephony.SubscriptionManager;
46import android.telephony.TelephonyManager;
47import android.text.TextUtils;
48
49// TODO: Needed for move to system service: import com.android.internal.R;
50import com.android.internal.telecom.ITelecomService;
51import com.android.internal.util.IndentingPrintWriter;
Yorke Leea3a3adc2015-04-23 12:49:01 -070052import com.android.server.telecom.components.UserCallIntentProcessor;
Santos Cordonf987d1a2014-12-02 03:37:03 -080053
54import java.io.FileDescriptor;
55import java.io.PrintWriter;
56import java.util.ArrayList;
Svet Ganov09611182015-04-16 12:29:01 -070057import java.util.Collections;
Santos Cordonf987d1a2014-12-02 03:37:03 -080058import java.util.List;
59
60/**
61 * Implementation of the ITelecom interface.
62 */
Ihab Awad78a5e6b2015-02-06 10:13:05 -080063public class TelecomServiceImpl {
Santos Cordon73853962015-02-27 15:13:35 -080064 private static final String PERMISSION_PROCESS_PHONE_ACCOUNT_REGISTRATION =
65 "android.permission.PROCESS_PHONE_ACCOUNT_REGISTRATION";
66
Ihab Awad8d5d9dd2015-03-12 11:11:06 -070067 private final ITelecomService.Stub mBinderImpl = new ITelecomService.Stub() {
Santos Cordonf987d1a2014-12-02 03:37:03 -080068 @Override
Svet Ganov09611182015-04-16 12:29:01 -070069 public PhoneAccountHandle getDefaultOutgoingPhoneAccount(String uriScheme,
70 String callingPackage) {
Ihab Awad8d5d9dd2015-03-12 11:11:06 -070071 synchronized (mLock) {
Svet Ganov38f1a4d2015-04-17 15:28:03 -070072 if (!canReadPhoneState(callingPackage, "getDefaultOutgoingPhoneAccount")) {
Svet Ganov09611182015-04-16 12:29:01 -070073 return null;
74 }
75
Ihab Awad8d5d9dd2015-03-12 11:11:06 -070076 long token = Binder.clearCallingIdentity();
77 try {
78 PhoneAccountHandle defaultOutgoingPhoneAccount =
Santos Cordon6a212642015-05-08 16:35:23 -070079 mPhoneAccountRegistrar.getOutgoingPhoneAccountForScheme(uriScheme);
Ihab Awad8d5d9dd2015-03-12 11:11:06 -070080 // Make sure that the calling user can see this phone account.
Santos Cordonebf2d0f2015-05-15 10:28:29 -070081 // TODO: Does this isVisible check actually work considering we are clearing
82 // the calling identity?
Ihab Awad8d5d9dd2015-03-12 11:11:06 -070083 if (defaultOutgoingPhoneAccount != null
84 && !isVisibleToCaller(defaultOutgoingPhoneAccount)) {
85 Log.w(this, "No account found for the calling user");
86 return null;
87 }
88 return defaultOutgoingPhoneAccount;
89 } catch (Exception e) {
90 Log.e(this, e, "getDefaultOutgoingPhoneAccount");
91 throw e;
92 } finally {
93 Binder.restoreCallingIdentity(token);
Santos Cordonf987d1a2014-12-02 03:37:03 -080094 }
Santos Cordonf987d1a2014-12-02 03:37:03 -080095 }
96 }
97
98 @Override
99 public PhoneAccountHandle getUserSelectedOutgoingPhoneAccount() {
Ihab Awad8d5d9dd2015-03-12 11:11:06 -0700100 synchronized (mLock) {
101 try {
102 PhoneAccountHandle userSelectedOutgoingPhoneAccount =
103 mPhoneAccountRegistrar.getUserSelectedOutgoingPhoneAccount();
104 // Make sure that the calling user can see this phone account.
105 if (!isVisibleToCaller(userSelectedOutgoingPhoneAccount)) {
106 Log.w(this, "No account found for the calling user");
107 return null;
108 }
109 return userSelectedOutgoingPhoneAccount;
110 } catch (Exception e) {
111 Log.e(this, e, "getUserSelectedOutgoingPhoneAccount");
112 throw e;
Santos Cordonf987d1a2014-12-02 03:37:03 -0800113 }
Santos Cordonf987d1a2014-12-02 03:37:03 -0800114 }
115 }
116
117 @Override
118 public void setUserSelectedOutgoingPhoneAccount(PhoneAccountHandle accountHandle) {
Ihab Awad8d5d9dd2015-03-12 11:11:06 -0700119 synchronized (mLock) {
120 enforceModifyPermission();
Santos Cordonebf2d0f2015-05-15 10:28:29 -0700121
122 long token = Binder.clearCallingIdentity();
Ihab Awad8d5d9dd2015-03-12 11:11:06 -0700123 try {
124 mPhoneAccountRegistrar.setUserSelectedOutgoingPhoneAccount(accountHandle);
125 } catch (Exception e) {
126 Log.e(this, e, "setUserSelectedOutgoingPhoneAccount");
127 throw e;
Santos Cordonebf2d0f2015-05-15 10:28:29 -0700128 } finally {
129 Binder.restoreCallingIdentity(token);
Ihab Awad8d5d9dd2015-03-12 11:11:06 -0700130 }
Santos Cordonf987d1a2014-12-02 03:37:03 -0800131 }
132 }
133
134 @Override
Santos Cordonea5cb932015-05-07 16:28:38 -0700135 public List<PhoneAccountHandle> getCallCapablePhoneAccounts(
136 boolean includeDisabledAccounts, String callingPackage) {
Svet Ganov38f1a4d2015-04-17 15:28:03 -0700137 if (!canReadPhoneState(callingPackage, "getDefaultOutgoingPhoneAccount")) {
Svet Ganov09611182015-04-16 12:29:01 -0700138 return Collections.emptyList();
139 }
140
Ihab Awad8d5d9dd2015-03-12 11:11:06 -0700141 synchronized (mLock) {
Ihab Awad8d5d9dd2015-03-12 11:11:06 -0700142 long token = Binder.clearCallingIdentity();
143 try {
Santos Cordonebf2d0f2015-05-15 10:28:29 -0700144 // TODO: Does this isVisible check actually work considering we are clearing
145 // the calling identity?
Ihab Awad8d5d9dd2015-03-12 11:11:06 -0700146 return filterForAccountsVisibleToCaller(
Santos Cordonea5cb932015-05-07 16:28:38 -0700147 mPhoneAccountRegistrar.getCallCapablePhoneAccounts(
148 null, includeDisabledAccounts));
Ihab Awad8d5d9dd2015-03-12 11:11:06 -0700149 } catch (Exception e) {
150 Log.e(this, e, "getCallCapablePhoneAccounts");
151 throw e;
152 } finally {
153 Binder.restoreCallingIdentity(token);
154 }
Santos Cordonf987d1a2014-12-02 03:37:03 -0800155 }
156 }
157
158 @Override
Svet Ganov09611182015-04-16 12:29:01 -0700159 public List<PhoneAccountHandle> getPhoneAccountsSupportingScheme(String uriScheme,
160 String callingPackage) {
Ihab Awad8d5d9dd2015-03-12 11:11:06 -0700161 synchronized (mLock) {
Svet Ganov38f1a4d2015-04-17 15:28:03 -0700162 if (!canReadPhoneState(callingPackage, "getPhoneAccountsSupportingScheme")) {
Svet Ganov09611182015-04-16 12:29:01 -0700163 return Collections.emptyList();
164 }
165
Ihab Awad8d5d9dd2015-03-12 11:11:06 -0700166 long token = Binder.clearCallingIdentity();
167 try {
Santos Cordonebf2d0f2015-05-15 10:28:29 -0700168 // TODO: Does this isVisible check actually work considering we are clearing
169 // the calling identity?
Ihab Awad8d5d9dd2015-03-12 11:11:06 -0700170 return filterForAccountsVisibleToCaller(
Santos Cordonea5cb932015-05-07 16:28:38 -0700171 mPhoneAccountRegistrar.getCallCapablePhoneAccounts(uriScheme, false));
Ihab Awad8d5d9dd2015-03-12 11:11:06 -0700172 } catch (Exception e) {
173 Log.e(this, e, "getPhoneAccountsSupportingScheme %s", uriScheme);
174 throw e;
175 } finally {
176 Binder.restoreCallingIdentity(token);
177 }
Santos Cordonf987d1a2014-12-02 03:37:03 -0800178 }
179 }
180
181 @Override
182 public List<PhoneAccountHandle> getPhoneAccountsForPackage(String packageName) {
Ihab Awad8d5d9dd2015-03-12 11:11:06 -0700183 synchronized (mLock) {
184 try {
185 return filterForAccountsVisibleToCaller(
186 mPhoneAccountRegistrar.getPhoneAccountsForPackage(packageName));
187 } catch (Exception e) {
188 Log.e(this, e, "getPhoneAccountsForPackage %s", packageName);
189 throw e;
190 }
Santos Cordonf987d1a2014-12-02 03:37:03 -0800191 }
192 }
193
194 @Override
195 public PhoneAccount getPhoneAccount(PhoneAccountHandle accountHandle) {
Ihab Awad8d5d9dd2015-03-12 11:11:06 -0700196 synchronized (mLock) {
197 try {
198 if (!isVisibleToCaller(accountHandle)) {
Roshan Pius31822392015-06-09 14:36:08 -0700199 Log.d(this, "%s is not visible for the calling user [gPA]", accountHandle);
Ihab Awad8d5d9dd2015-03-12 11:11:06 -0700200 return null;
201 }
Santos Cordon6a212642015-05-08 16:35:23 -0700202 // TODO: Do we really want to return for *any* user?
203 return mPhoneAccountRegistrar.getPhoneAccount(accountHandle);
Ihab Awad8d5d9dd2015-03-12 11:11:06 -0700204 } catch (Exception e) {
205 Log.e(this, e, "getPhoneAccount %s", accountHandle);
206 throw e;
Santos Cordonf987d1a2014-12-02 03:37:03 -0800207 }
Santos Cordonf987d1a2014-12-02 03:37:03 -0800208 }
209 }
210
211 @Override
212 public int getAllPhoneAccountsCount() {
Ihab Awad8d5d9dd2015-03-12 11:11:06 -0700213 synchronized (mLock) {
214 try {
215 // This list is pre-filtered for the calling user.
216 return getAllPhoneAccounts().size();
217 } catch (Exception e) {
218 Log.e(this, e, "getAllPhoneAccountsCount");
219 throw e;
220 }
Santos Cordonf987d1a2014-12-02 03:37:03 -0800221 }
222 }
223
224 @Override
225 public List<PhoneAccount> getAllPhoneAccounts() {
Ihab Awad8d5d9dd2015-03-12 11:11:06 -0700226 synchronized (mLock) {
227 try {
228 List<PhoneAccount> allPhoneAccounts = mPhoneAccountRegistrar
229 .getAllPhoneAccounts();
230 List<PhoneAccount> profilePhoneAccounts = new ArrayList<>(
231 allPhoneAccounts.size());
232 for (PhoneAccount phoneAccount : profilePhoneAccounts) {
233 if (isVisibleToCaller(phoneAccount)) {
234 profilePhoneAccounts.add(phoneAccount);
235 }
Santos Cordonf987d1a2014-12-02 03:37:03 -0800236 }
Ihab Awad8d5d9dd2015-03-12 11:11:06 -0700237 return profilePhoneAccounts;
238 } catch (Exception e) {
239 Log.e(this, e, "getAllPhoneAccounts");
240 throw e;
Santos Cordonf987d1a2014-12-02 03:37:03 -0800241 }
Santos Cordonf987d1a2014-12-02 03:37:03 -0800242 }
243 }
244
245 @Override
246 public List<PhoneAccountHandle> getAllPhoneAccountHandles() {
Ihab Awad8d5d9dd2015-03-12 11:11:06 -0700247 synchronized (mLock) {
248 try {
249 return filterForAccountsVisibleToCaller(
250 mPhoneAccountRegistrar.getAllPhoneAccountHandles());
251 } catch (Exception e) {
252 Log.e(this, e, "getAllPhoneAccounts");
253 throw e;
254 }
Santos Cordonf987d1a2014-12-02 03:37:03 -0800255 }
256 }
257
258 @Override
259 public PhoneAccountHandle getSimCallManager() {
Ihab Awad8d5d9dd2015-03-12 11:11:06 -0700260 synchronized (mLock) {
261 try {
262 PhoneAccountHandle accountHandle = mPhoneAccountRegistrar.getSimCallManager();
263 if (!isVisibleToCaller(accountHandle)) {
Roshan Pius31822392015-06-09 14:36:08 -0700264 Log.d(this, "%s is not visible for the calling user [gsCM]", accountHandle);
Ihab Awad8d5d9dd2015-03-12 11:11:06 -0700265 return null;
266 }
267 return accountHandle;
268 } catch (Exception e) {
269 Log.e(this, e, "getSimCallManager");
270 throw e;
Santos Cordonf987d1a2014-12-02 03:37:03 -0800271 }
Santos Cordonf987d1a2014-12-02 03:37:03 -0800272 }
273 }
274
275 @Override
276 public void setSimCallManager(PhoneAccountHandle accountHandle) {
Ihab Awad8d5d9dd2015-03-12 11:11:06 -0700277 synchronized (mLock) {
278 enforceModifyPermission();
279 try {
280 mPhoneAccountRegistrar.setSimCallManager(accountHandle);
281 } catch (Exception e) {
282 Log.e(this, e, "setSimCallManager");
283 throw e;
284 }
Santos Cordonf987d1a2014-12-02 03:37:03 -0800285 }
286 }
287
288 @Override
Svet Ganov09611182015-04-16 12:29:01 -0700289 public List<PhoneAccountHandle> getSimCallManagers(String callingPackage) {
Ihab Awad8d5d9dd2015-03-12 11:11:06 -0700290 synchronized (mLock) {
Svet Ganov38f1a4d2015-04-17 15:28:03 -0700291 if (!canReadPhoneState(callingPackage, "getSimCallManagers")) {
Svet Ganov09611182015-04-16 12:29:01 -0700292 return Collections.emptyList();
293 }
294
Ihab Awad8d5d9dd2015-03-12 11:11:06 -0700295 long token = Binder.clearCallingIdentity();
296 try {
Santos Cordonebf2d0f2015-05-15 10:28:29 -0700297 // TODO: Does this isVisible check actually work considering we are clearing
298 // the calling identity?
Ihab Awad8d5d9dd2015-03-12 11:11:06 -0700299 return filterForAccountsVisibleToCaller(
300 mPhoneAccountRegistrar.getConnectionManagerPhoneAccounts());
301 } catch (Exception e) {
302 Log.e(this, e, "getSimCallManagers");
303 throw e;
304 } finally {
305 Binder.restoreCallingIdentity(token);
306 }
Santos Cordonf987d1a2014-12-02 03:37:03 -0800307 }
308 }
309
310 @Override
311 public void registerPhoneAccount(PhoneAccount account) {
Ihab Awad8d5d9dd2015-03-12 11:11:06 -0700312 synchronized (mLock) {
Roshan Pius472aa6c2015-06-11 12:37:59 -0700313 if (!mContext.getApplicationContext().getResources().getBoolean(
314 com.android.internal.R.bool.config_voice_capable)) {
315 Log.w(this, "registerPhoneAccount not allowed on non-voice capable device.");
316 return;
317 }
Ihab Awad8d5d9dd2015-03-12 11:11:06 -0700318 try {
319 enforcePhoneAccountModificationForPackage(
320 account.getAccountHandle().getComponentName().getPackageName());
Ihab Awad8d5d9dd2015-03-12 11:11:06 -0700321 if (account.hasCapabilities(PhoneAccount.CAPABILITY_SIM_SUBSCRIPTION)) {
322 enforceRegisterSimSubscriptionPermission();
323 }
Ihab Awad8d5d9dd2015-03-12 11:11:06 -0700324 if (account.hasCapabilities(PhoneAccount.CAPABILITY_MULTI_USER)) {
325 enforceRegisterMultiUser();
326 }
327 enforceUserHandleMatchesCaller(account.getAccountHandle());
Santos Cordonf987d1a2014-12-02 03:37:03 -0800328
Ihab Awad8d5d9dd2015-03-12 11:11:06 -0700329 mPhoneAccountRegistrar.registerPhoneAccount(account);
Santos Cordon73853962015-02-27 15:13:35 -0800330
Ihab Awad8d5d9dd2015-03-12 11:11:06 -0700331 // Broadcast an intent indicating the phone account which was registered.
332 long token = Binder.clearCallingIdentity();
Yorke Lee58061752015-05-04 11:06:26 -0700333 try {
334 Intent intent = new Intent(TelecomManager.ACTION_PHONE_ACCOUNT_REGISTERED);
335 intent.putExtra(TelecomManager.EXTRA_PHONE_ACCOUNT_HANDLE,
336 account.getAccountHandle());
337 Log.i(this, "Sending phone-account intent as user");
338 mContext.sendBroadcastAsUser(intent, UserHandle.ALL,
339 PERMISSION_PROCESS_PHONE_ACCOUNT_REGISTRATION);
340 } finally {
341 Binder.restoreCallingIdentity(token);
342 }
Ihab Awad8d5d9dd2015-03-12 11:11:06 -0700343 } catch (Exception e) {
344 Log.e(this, e, "registerPhoneAccount %s", account);
345 throw e;
346 }
Santos Cordonf987d1a2014-12-02 03:37:03 -0800347 }
348 }
349
350 @Override
351 public void unregisterPhoneAccount(PhoneAccountHandle accountHandle) {
Ihab Awad8d5d9dd2015-03-12 11:11:06 -0700352 synchronized (mLock) {
353 try {
354 enforcePhoneAccountModificationForPackage(
355 accountHandle.getComponentName().getPackageName());
356 enforceUserHandleMatchesCaller(accountHandle);
357 mPhoneAccountRegistrar.unregisterPhoneAccount(accountHandle);
358 } catch (Exception e) {
359 Log.e(this, e, "unregisterPhoneAccount %s", accountHandle);
360 throw e;
361 }
Santos Cordonf987d1a2014-12-02 03:37:03 -0800362 }
363 }
364
365 @Override
366 public void clearAccounts(String packageName) {
Ihab Awad8d5d9dd2015-03-12 11:11:06 -0700367 synchronized (mLock) {
368 try {
369 enforcePhoneAccountModificationForPackage(packageName);
370 mPhoneAccountRegistrar
371 .clearAccounts(packageName, Binder.getCallingUserHandle());
372 } catch (Exception e) {
373 Log.e(this, e, "clearAccounts %s", packageName);
374 throw e;
375 }
Santos Cordonf987d1a2014-12-02 03:37:03 -0800376 }
377 }
378
379 /**
380 * @see android.telecom.TelecomManager#isVoiceMailNumber
381 */
382 @Override
Svet Ganov09611182015-04-16 12:29:01 -0700383 public boolean isVoiceMailNumber(PhoneAccountHandle accountHandle, String number,
384 String callingPackage) {
Ihab Awad8d5d9dd2015-03-12 11:11:06 -0700385 synchronized (mLock) {
Yorke Lee57138a62015-05-18 18:18:08 -0700386 if (!canReadPhoneState(callingPackage, "isVoiceMailNumber")) {
Svet Ganov09611182015-04-16 12:29:01 -0700387 return false;
388 }
389
Santos Cordonebf2d0f2015-05-15 10:28:29 -0700390 if (!isVisibleToCaller(accountHandle)) {
Roshan Pius31822392015-06-09 14:36:08 -0700391 Log.d(this, "%s is not visible for the calling user [iVMN]", accountHandle);
Santos Cordonebf2d0f2015-05-15 10:28:29 -0700392 return false;
393 }
394
395 long token = Binder.clearCallingIdentity();
Ihab Awad8d5d9dd2015-03-12 11:11:06 -0700396 try {
Ihab Awad8d5d9dd2015-03-12 11:11:06 -0700397 return mPhoneAccountRegistrar.isVoiceMailNumber(accountHandle, number);
398 } catch (Exception e) {
399 Log.e(this, e, "getSubscriptionIdForPhoneAccount");
400 throw e;
Santos Cordonebf2d0f2015-05-15 10:28:29 -0700401 } finally {
402 Binder.restoreCallingIdentity(token);
Santos Cordonf987d1a2014-12-02 03:37:03 -0800403 }
Santos Cordonf987d1a2014-12-02 03:37:03 -0800404 }
405 }
406
407 /**
Yorke Leefb5ec302015-04-15 16:15:55 -0700408 * @see android.telecom.TelecomManager#getVoiceMailNumber
Santos Cordonf987d1a2014-12-02 03:37:03 -0800409 */
410 @Override
Svet Ganov09611182015-04-16 12:29:01 -0700411 public String getVoiceMailNumber(PhoneAccountHandle accountHandle, String callingPackage) {
Ihab Awad8d5d9dd2015-03-12 11:11:06 -0700412 synchronized (mLock) {
Yorke Lee57138a62015-05-18 18:18:08 -0700413 if (!canReadPhoneState(callingPackage, "getVoiceMailNumber")) {
Svet Ganov09611182015-04-16 12:29:01 -0700414 return null;
415 }
416
Ihab Awad8d5d9dd2015-03-12 11:11:06 -0700417 try {
418 if (!isVisibleToCaller(accountHandle)) {
Roshan Pius31822392015-06-09 14:36:08 -0700419 Log.d(this, "%s is not visible for the calling user [gVMN]", accountHandle);
Yorke Leefb5ec302015-04-15 16:15:55 -0700420 return null;
Ihab Awad8d5d9dd2015-03-12 11:11:06 -0700421 }
Santos Cordonf987d1a2014-12-02 03:37:03 -0800422
Ihab Awad8d5d9dd2015-03-12 11:11:06 -0700423 int subId = SubscriptionManager.getDefaultVoiceSubId();
424 if (accountHandle != null) {
425 subId = mPhoneAccountRegistrar
426 .getSubscriptionIdForPhoneAccount(accountHandle);
427 }
Yorke Leefb5ec302015-04-15 16:15:55 -0700428 return getTelephonyManager().getVoiceMailNumber(subId);
Ihab Awad8d5d9dd2015-03-12 11:11:06 -0700429 } catch (Exception e) {
430 Log.e(this, e, "getSubscriptionIdForPhoneAccount");
431 throw e;
Ihab Awad78a5e6b2015-02-06 10:13:05 -0800432 }
Santos Cordonf987d1a2014-12-02 03:37:03 -0800433 }
434 }
435
436 /**
Nancy Chenba304752015-01-24 23:29:22 -0800437 * @see android.telecom.TelecomManager#getLine1Number
438 */
439 @Override
Svet Ganov09611182015-04-16 12:29:01 -0700440 public String getLine1Number(PhoneAccountHandle accountHandle, String callingPackage) {
Yorke Lee57138a62015-05-18 18:18:08 -0700441 if (!canReadPhoneState(callingPackage, "getLine1Number")) {
Svet Ganov09611182015-04-16 12:29:01 -0700442 return null;
443 }
444
Ihab Awad8d5d9dd2015-03-12 11:11:06 -0700445 synchronized (mLock) {
Santos Cordonebf2d0f2015-05-15 10:28:29 -0700446 if (!isVisibleToCaller(accountHandle)) {
Roshan Pius31822392015-06-09 14:36:08 -0700447 Log.d(this, "%s is not visible for the calling user [gL1N]", accountHandle);
Santos Cordonebf2d0f2015-05-15 10:28:29 -0700448 return null;
449 }
450
451 long token = Binder.clearCallingIdentity();
Ihab Awad8d5d9dd2015-03-12 11:11:06 -0700452 try {
Ihab Awad8d5d9dd2015-03-12 11:11:06 -0700453 int subId =
454 mPhoneAccountRegistrar.getSubscriptionIdForPhoneAccount(accountHandle);
455 return getTelephonyManager().getLine1NumberForSubscriber(subId);
456 } catch (Exception e) {
457 Log.e(this, e, "getSubscriptionIdForPhoneAccount");
458 throw e;
Santos Cordonebf2d0f2015-05-15 10:28:29 -0700459 } finally {
460 Binder.restoreCallingIdentity(token);
Nancy Chenba304752015-01-24 23:29:22 -0800461 }
Nancy Chenba304752015-01-24 23:29:22 -0800462 }
463 }
464
465 /**
Santos Cordonf987d1a2014-12-02 03:37:03 -0800466 * @see android.telecom.TelecomManager#silenceRinger
467 */
468 @Override
Yorke Lee53101962015-04-29 16:25:29 -0700469 public void silenceRinger(String callingPackage) {
Ihab Awad8d5d9dd2015-03-12 11:11:06 -0700470 synchronized (mLock) {
Yorke Leecb0bd8a2015-05-18 11:57:14 -0700471 enforcePermissionOrPrivilegedDialer(MODIFY_PHONE_STATE, callingPackage);
Santos Cordonebf2d0f2015-05-15 10:28:29 -0700472
473 long token = Binder.clearCallingIdentity();
474 try {
Santos Cordona83f8a72015-06-02 17:12:39 -0700475 Log.i(this, "Silence Ringer requested by %s", callingPackage);
Santos Cordonebf2d0f2015-05-15 10:28:29 -0700476 mCallsManager.getRinger().silence();
477 } finally {
478 Binder.restoreCallingIdentity(token);
479 }
Ihab Awad8d5d9dd2015-03-12 11:11:06 -0700480 }
Santos Cordonf987d1a2014-12-02 03:37:03 -0800481 }
482
483 /**
484 * @see android.telecom.TelecomManager#getDefaultPhoneApp
Yorke Lee5b3fc0a2015-04-23 17:42:57 -0700485 * @deprecated - Use {@link android.telecom.TelecomManager#getDefaultDialerPackage()}
486 * instead.
Santos Cordonf987d1a2014-12-02 03:37:03 -0800487 */
488 @Override
489 public ComponentName getDefaultPhoneApp() {
Ihab Awad8d5d9dd2015-03-12 11:11:06 -0700490 // No need to synchronize
Santos Cordonf987d1a2014-12-02 03:37:03 -0800491 Resources resources = mContext.getResources();
492 return new ComponentName(
493 resources.getString(R.string.ui_default_package),
494 resources.getString(R.string.dialer_default_class));
495 }
496
497 /**
Yorke Lee5291d4a2015-04-24 16:42:36 -0700498 * @return the package name of the current user-selected default dialer. If no default
499 * has been selected, the package name of the system dialer is returned. If
500 * neither exists, then {@code null} is returned.
Yorke Lee5b3fc0a2015-04-23 17:42:57 -0700501 * @see android.telecom.TelecomManager#getDefaultDialerPackage
502 */
503 @Override
504 public String getDefaultDialerPackage() {
Yorke Lee29c003e2015-05-04 17:09:27 -0700505 final long token = Binder.clearCallingIdentity();
506 try {
507 return DefaultDialerManager.getDefaultDialerApplication(mContext);
508 } finally {
509 Binder.restoreCallingIdentity(token);
510 }
Yorke Lee5b3fc0a2015-04-23 17:42:57 -0700511 }
512
513 /**
514 * @see android.telecom.TelecomManager#getSystemDialerPackage
515 */
516 @Override
517 public String getSystemDialerPackage() {
518 return mContext.getResources().getString(R.string.ui_default_package);
519 }
520
521 /**
Santos Cordonf987d1a2014-12-02 03:37:03 -0800522 * @see android.telecom.TelecomManager#isInCall
523 */
524 @Override
Svet Ganov09611182015-04-16 12:29:01 -0700525 public boolean isInCall(String callingPackage) {
Svet Ganov38f1a4d2015-04-17 15:28:03 -0700526 if (!canReadPhoneState(callingPackage, "isInCall")) {
527 return false;
Svet Ganov09611182015-04-16 12:29:01 -0700528 }
529
Ihab Awad8d5d9dd2015-03-12 11:11:06 -0700530 synchronized (mLock) {
Ihab Awad8d5d9dd2015-03-12 11:11:06 -0700531 final int callState = mCallsManager.getCallState();
532 return callState == TelephonyManager.CALL_STATE_OFFHOOK
533 || callState == TelephonyManager.CALL_STATE_RINGING;
534 }
Santos Cordonf987d1a2014-12-02 03:37:03 -0800535 }
536
537 /**
538 * @see android.telecom.TelecomManager#isRinging
539 */
540 @Override
Svet Ganov09611182015-04-16 12:29:01 -0700541 public boolean isRinging(String callingPackage) {
Svet Ganov38f1a4d2015-04-17 15:28:03 -0700542 if (!canReadPhoneState(callingPackage, "isRinging")) {
543 return false;
Svet Ganov09611182015-04-16 12:29:01 -0700544 }
545
Ihab Awad8d5d9dd2015-03-12 11:11:06 -0700546 synchronized (mLock) {
Ihab Awad8d5d9dd2015-03-12 11:11:06 -0700547 return mCallsManager.getCallState() == TelephonyManager.CALL_STATE_RINGING;
548 }
Santos Cordonf987d1a2014-12-02 03:37:03 -0800549 }
550
551 /**
552 * @see TelecomManager#getCallState
553 */
554 @Override
555 public int getCallState() {
Ihab Awad8d5d9dd2015-03-12 11:11:06 -0700556 synchronized (mLock) {
557 return mCallsManager.getCallState();
558 }
Santos Cordonf987d1a2014-12-02 03:37:03 -0800559 }
560
561 /**
562 * @see android.telecom.TelecomManager#endCall
563 */
564 @Override
565 public boolean endCall() {
Ihab Awad8d5d9dd2015-03-12 11:11:06 -0700566 synchronized (mLock) {
567 enforceModifyPermission();
Santos Cordonebf2d0f2015-05-15 10:28:29 -0700568
569 long token = Binder.clearCallingIdentity();
570 try {
571 return endCallInternal();
572 } finally {
573 Binder.restoreCallingIdentity(token);
574 }
Ihab Awad8d5d9dd2015-03-12 11:11:06 -0700575 }
Santos Cordonf987d1a2014-12-02 03:37:03 -0800576 }
577
578 /**
579 * @see android.telecom.TelecomManager#acceptRingingCall
580 */
581 @Override
582 public void acceptRingingCall() {
Ihab Awad8d5d9dd2015-03-12 11:11:06 -0700583 synchronized (mLock) {
584 enforceModifyPermission();
Santos Cordonebf2d0f2015-05-15 10:28:29 -0700585
586 long token = Binder.clearCallingIdentity();
587 try {
588 acceptRingingCallInternal();
589 } finally {
590 Binder.restoreCallingIdentity(token);
591 }
Ihab Awad8d5d9dd2015-03-12 11:11:06 -0700592 }
Santos Cordonf987d1a2014-12-02 03:37:03 -0800593 }
594
595 /**
596 * @see android.telecom.TelecomManager#showInCallScreen
597 */
598 @Override
Svet Ganov09611182015-04-16 12:29:01 -0700599 public void showInCallScreen(boolean showDialpad, String callingPackage) {
Yorke Lee57138a62015-05-18 18:18:08 -0700600 if (!canReadPhoneState(callingPackage, "showInCallScreen")) {
Svet Ganov09611182015-04-16 12:29:01 -0700601 return;
602 }
603
Ihab Awad8d5d9dd2015-03-12 11:11:06 -0700604 synchronized (mLock) {
Santos Cordonebf2d0f2015-05-15 10:28:29 -0700605
606 long token = Binder.clearCallingIdentity();
607 try {
608 mCallsManager.getInCallController().bringToForeground(showDialpad);
609 } finally {
610 Binder.restoreCallingIdentity(token);
611 }
Ihab Awad8d5d9dd2015-03-12 11:11:06 -0700612 }
Santos Cordonf987d1a2014-12-02 03:37:03 -0800613 }
614
615 /**
616 * @see android.telecom.TelecomManager#cancelMissedCallsNotification
617 */
618 @Override
Yorke Lee53101962015-04-29 16:25:29 -0700619 public void cancelMissedCallsNotification(String callingPackage) {
Ihab Awad8d5d9dd2015-03-12 11:11:06 -0700620 synchronized (mLock) {
Yorke Leecb0bd8a2015-05-18 11:57:14 -0700621 enforcePermissionOrPrivilegedDialer(MODIFY_PHONE_STATE, callingPackage);
Santos Cordonebf2d0f2015-05-15 10:28:29 -0700622 long token = Binder.clearCallingIdentity();
623 try {
624 mCallsManager.getMissedCallNotifier().clearMissedCalls();
625 } finally {
626 Binder.restoreCallingIdentity(token);
627 }
Ihab Awad8d5d9dd2015-03-12 11:11:06 -0700628 }
Santos Cordonf987d1a2014-12-02 03:37:03 -0800629 }
630
631 /**
632 * @see android.telecom.TelecomManager#handleMmi
633 */
634 @Override
Yorke Lee53101962015-04-29 16:25:29 -0700635 public boolean handlePinMmi(String dialString, String callingPackage) {
Ihab Awad8d5d9dd2015-03-12 11:11:06 -0700636 synchronized (mLock) {
Yorke Leecb0bd8a2015-05-18 11:57:14 -0700637 enforcePermissionOrPrivilegedDialer(MODIFY_PHONE_STATE, callingPackage);
Santos Cordonf987d1a2014-12-02 03:37:03 -0800638
Ihab Awad8d5d9dd2015-03-12 11:11:06 -0700639 // Switch identity so that TelephonyManager checks Telecom's permissions instead.
640 long token = Binder.clearCallingIdentity();
641 boolean retval = false;
642 try {
643 retval = getTelephonyManager().handlePinMmi(dialString);
644 } finally {
645 Binder.restoreCallingIdentity(token);
646 }
647
648 return retval;
Santos Cordonf987d1a2014-12-02 03:37:03 -0800649 }
Santos Cordonf987d1a2014-12-02 03:37:03 -0800650 }
651
652 /**
653 * @see android.telecom.TelecomManager#handleMmi
654 */
655 @Override
Ihab Awad8d5d9dd2015-03-12 11:11:06 -0700656 public boolean handlePinMmiForPhoneAccount(
657 PhoneAccountHandle accountHandle,
Yorke Lee53101962015-04-29 16:25:29 -0700658 String dialString,
659 String callingPackage) {
Ihab Awad8d5d9dd2015-03-12 11:11:06 -0700660 synchronized (mLock) {
Yorke Leecb0bd8a2015-05-18 11:57:14 -0700661 enforcePermissionOrPrivilegedDialer(MODIFY_PHONE_STATE, callingPackage);
Santos Cordonf987d1a2014-12-02 03:37:03 -0800662
Ihab Awad8d5d9dd2015-03-12 11:11:06 -0700663 if (!isVisibleToCaller(accountHandle)) {
Roshan Pius31822392015-06-09 14:36:08 -0700664 Log.d(this, "%s is not visible for the calling user [hMMI]", accountHandle);
Ihab Awad8d5d9dd2015-03-12 11:11:06 -0700665 return false;
666 }
667
668 // Switch identity so that TelephonyManager checks Telecom's permissions instead.
669 long token = Binder.clearCallingIdentity();
670 boolean retval = false;
671 try {
672 int subId = mPhoneAccountRegistrar
673 .getSubscriptionIdForPhoneAccount(accountHandle);
674 retval = getTelephonyManager().handlePinMmiForSubscriber(subId, dialString);
675 } finally {
676 Binder.restoreCallingIdentity(token);
677 }
678
679 return retval;
Santos Cordonf987d1a2014-12-02 03:37:03 -0800680 }
Santos Cordonf987d1a2014-12-02 03:37:03 -0800681 }
682
683 /**
684 * @see android.telecom.TelecomManager#getAdnUriForPhoneAccount
685 */
686 @Override
Yorke Lee53101962015-04-29 16:25:29 -0700687 public Uri getAdnUriForPhoneAccount(PhoneAccountHandle accountHandle,
688 String callingPackage) {
Ihab Awad8d5d9dd2015-03-12 11:11:06 -0700689 synchronized (mLock) {
Yorke Leecb0bd8a2015-05-18 11:57:14 -0700690 enforcePermissionOrPrivilegedDialer(MODIFY_PHONE_STATE, callingPackage);
Santos Cordonf987d1a2014-12-02 03:37:03 -0800691
Ihab Awad8d5d9dd2015-03-12 11:11:06 -0700692 if (!isVisibleToCaller(accountHandle)) {
Roshan Pius31822392015-06-09 14:36:08 -0700693 Log.d(this, "%s is not visible for the calling user [gA4PA]", accountHandle);
Ihab Awad8d5d9dd2015-03-12 11:11:06 -0700694 return null;
695 }
696
697 // Switch identity so that TelephonyManager checks Telecom's permissions instead.
698 long token = Binder.clearCallingIdentity();
699 String retval = "content://icc/adn/";
700 try {
701 long subId = mPhoneAccountRegistrar
702 .getSubscriptionIdForPhoneAccount(accountHandle);
703 retval = retval + "subId/" + subId;
704 } finally {
705 Binder.restoreCallingIdentity(token);
706 }
707
708 return Uri.parse(retval);
Santos Cordonf987d1a2014-12-02 03:37:03 -0800709 }
Santos Cordonf987d1a2014-12-02 03:37:03 -0800710 }
711
712 /**
713 * @see android.telecom.TelecomManager#isTtySupported
714 */
715 @Override
Svet Ganov09611182015-04-16 12:29:01 -0700716 public boolean isTtySupported(String callingPackage) {
Svet Ganov38f1a4d2015-04-17 15:28:03 -0700717 if (!canReadPhoneState(callingPackage, "hasVoiceMailNumber")) {
718 return false;
Svet Ganov09611182015-04-16 12:29:01 -0700719 }
720
Ihab Awad8d5d9dd2015-03-12 11:11:06 -0700721 synchronized (mLock) {
Ihab Awad8d5d9dd2015-03-12 11:11:06 -0700722 return mCallsManager.isTtySupported();
723 }
Santos Cordonf987d1a2014-12-02 03:37:03 -0800724 }
725
726 /**
727 * @see android.telecom.TelecomManager#getCurrentTtyMode
728 */
729 @Override
Svet Ganov09611182015-04-16 12:29:01 -0700730 public int getCurrentTtyMode(String callingPackage) {
Svet Ganov38f1a4d2015-04-17 15:28:03 -0700731 if (!canReadPhoneState(callingPackage, "getCurrentTtyMode")) {
Svet Ganov09611182015-04-16 12:29:01 -0700732 return TelecomManager.TTY_MODE_OFF;
733 }
734
Ihab Awad8d5d9dd2015-03-12 11:11:06 -0700735 synchronized (mLock) {
Ihab Awad8d5d9dd2015-03-12 11:11:06 -0700736 return mCallsManager.getCurrentTtyMode();
737 }
Santos Cordonf987d1a2014-12-02 03:37:03 -0800738 }
739
740 /**
741 * @see android.telecom.TelecomManager#addNewIncomingCall
742 */
743 @Override
744 public void addNewIncomingCall(PhoneAccountHandle phoneAccountHandle, Bundle extras) {
Ihab Awad8d5d9dd2015-03-12 11:11:06 -0700745 synchronized (mLock) {
746 Log.i(this, "Adding new incoming call with phoneAccountHandle %s",
747 phoneAccountHandle);
748 if (phoneAccountHandle != null && phoneAccountHandle.getComponentName() != null) {
Sailesh Nepal83b68642015-06-14 19:09:50 -0700749 // TODO(sail): Add unit tests for adding incoming calls from a SIM call manager.
750 if (isCallerSimCallManager() && TelephonyUtil.isPstnComponentName(
751 phoneAccountHandle.getComponentName())) {
752 Log.v(this, "Allowing call manager to add incoming call with PSTN handle");
753 } else {
754 mAppOpsManager.checkPackage(
755 Binder.getCallingUid(),
756 phoneAccountHandle.getComponentName().getPackageName());
757 // Make sure it doesn't cross the UserHandle boundary
758 enforceUserHandleMatchesCaller(phoneAccountHandle);
759 }
Ihab Awad8d5d9dd2015-03-12 11:11:06 -0700760
Sharvil Nanavati6d3efb42015-05-14 11:36:40 -0700761 long token = Binder.clearCallingIdentity();
Sharvil Nanavati6d3efb42015-05-14 11:36:40 -0700762 try {
763 Intent intent = new Intent(TelecomManager.ACTION_INCOMING_CALL);
764 intent.putExtra(TelecomManager.EXTRA_PHONE_ACCOUNT_HANDLE,
765 phoneAccountHandle);
766 intent.putExtra(CallIntentProcessor.KEY_IS_INCOMING_CALL, true);
767 if (extras != null) {
768 intent.putExtra(TelecomManager.EXTRA_INCOMING_CALL_EXTRAS, extras);
769 }
770 CallIntentProcessor.processIncomingCallIntent(mCallsManager, intent);
771 } finally {
772 Binder.restoreCallingIdentity(token);
Ihab Awad8d5d9dd2015-03-12 11:11:06 -0700773 }
Ihab Awad8d5d9dd2015-03-12 11:11:06 -0700774 } else {
775 Log.w(this,
776 "Null phoneAccountHandle. Ignoring request to add new incoming call");
Santos Cordonf987d1a2014-12-02 03:37:03 -0800777 }
Santos Cordonf987d1a2014-12-02 03:37:03 -0800778 }
779 }
780
781 /**
782 * @see android.telecom.TelecomManager#addNewUnknownCall
783 */
784 @Override
785 public void addNewUnknownCall(PhoneAccountHandle phoneAccountHandle, Bundle extras) {
Ihab Awad8d5d9dd2015-03-12 11:11:06 -0700786 synchronized (mLock) {
David Stevens07852742015-04-10 18:22:47 -0700787 if (phoneAccountHandle != null && phoneAccountHandle.getComponentName() != null) {
Ihab Awad8d5d9dd2015-03-12 11:11:06 -0700788 mAppOpsManager.checkPackage(
789 Binder.getCallingUid(),
790 phoneAccountHandle.getComponentName().getPackageName());
Santos Cordonf987d1a2014-12-02 03:37:03 -0800791
Ihab Awad8d5d9dd2015-03-12 11:11:06 -0700792 // Make sure it doesn't cross the UserHandle boundary
793 enforceUserHandleMatchesCaller(phoneAccountHandle);
Sharvil Nanavati6d3efb42015-05-14 11:36:40 -0700794 long token = Binder.clearCallingIdentity();
Santos Cordonf987d1a2014-12-02 03:37:03 -0800795
Sharvil Nanavati6d3efb42015-05-14 11:36:40 -0700796 try {
797 Intent intent = new Intent(TelecomManager.ACTION_NEW_UNKNOWN_CALL);
798 intent.putExtras(extras);
799 intent.putExtra(CallIntentProcessor.KEY_IS_UNKNOWN_CALL, true);
800 intent.putExtra(TelecomManager.EXTRA_PHONE_ACCOUNT_HANDLE,
801 phoneAccountHandle);
802 CallIntentProcessor.processUnknownCallIntent(mCallsManager, intent);
803 } finally {
804 Binder.restoreCallingIdentity(token);
805 }
Ihab Awad8d5d9dd2015-03-12 11:11:06 -0700806 } else {
807 Log.i(this,
808 "Null phoneAccountHandle or not initiated by Telephony. " +
809 "Ignoring request to add new unknown call.");
810 }
Santos Cordonf987d1a2014-12-02 03:37:03 -0800811 }
812 }
Tyler Gunn47689862014-12-17 17:10:28 -0800813
814 /**
Yorke Leea3a3adc2015-04-23 12:49:01 -0700815 * @see android.telecom.TelecomManager#placeCall
816 */
817 @Override
818 public void placeCall(Uri handle, Bundle extras, String callingPackage) {
819 enforceCallingPackage(callingPackage);
Yorke Lee57138a62015-05-18 18:18:08 -0700820 if (!canCallPhone(callingPackage, "placeCall")) {
821 throw new SecurityException("Package " + callingPackage
822 + " is not allowed to place phone calls");
823 }
Yorke Leecb0bd8a2015-05-18 11:57:14 -0700824
Yorke Leea3a3adc2015-04-23 12:49:01 -0700825 synchronized (mLock) {
Yorke Leeb3feab52015-04-30 12:35:16 -0700826 final UserHandle userHandle = Binder.getCallingUserHandle();
Yorke Leeb7910662015-04-24 12:00:19 -0700827 long token = Binder.clearCallingIdentity();
Yorke Lee58061752015-05-04 11:06:26 -0700828 try {
829 final Intent intent = new Intent(Intent.ACTION_CALL, handle);
830 intent.putExtras(extras);
831 new UserCallIntentProcessor(mContext, userHandle).processIntent(intent,
832 callingPackage);
833 } finally {
834 Binder.restoreCallingIdentity(token);
835 }
Yorke Leea3a3adc2015-04-23 12:49:01 -0700836 }
837 }
838
839 /**
Santos Cordonea5cb932015-05-07 16:28:38 -0700840 * @see android.telecom.TelecomManager#enablePhoneAccount
841 */
842 @Override
Yorke Lee71734c22015-06-02 14:22:56 -0700843 public boolean enablePhoneAccount(PhoneAccountHandle accountHandle, boolean isEnabled) {
Santos Cordonea5cb932015-05-07 16:28:38 -0700844 enforceModifyPermission();
845 synchronized (mLock) {
846 long token = Binder.clearCallingIdentity();
847 try {
848 // enable/disable phone account
Yorke Lee71734c22015-06-02 14:22:56 -0700849 return mPhoneAccountRegistrar.enablePhoneAccount(accountHandle, isEnabled);
850 } finally {
851 Binder.restoreCallingIdentity(token);
852 }
853 }
854 }
855
856 @Override
857 public boolean setDefaultDialer(String packageName) {
858 enforcePermission(MODIFY_PHONE_STATE);
859 enforcePermission(WRITE_SECURE_SETTINGS);
860 synchronized (mLock) {
861 long token = Binder.clearCallingIdentity();
862 try {
Yorke Leeb3984302015-06-15 12:06:35 -0700863 final boolean result =
864 DefaultDialerManager.setDefaultDialerApplication(mContext, packageName);
865 if (result) {
866 final Intent intent =
867 new Intent(TelecomManager.ACTION_DEFAULT_DIALER_CHANGED);
868 intent.putExtra(TelecomManager.EXTRA_CHANGE_DEFAULT_DIALER_PACKAGE_NAME,
869 packageName);
870 mContext.sendBroadcastAsUser(intent,
871 new UserHandle(ActivityManager.getCurrentUser()));
872 }
873 return result;
Santos Cordonea5cb932015-05-07 16:28:38 -0700874 } finally {
875 Binder.restoreCallingIdentity(token);
876 }
877 }
878 }
879
880 /**
Tyler Gunn47689862014-12-17 17:10:28 -0800881 * Dumps the current state of the TelecomService. Used when generating problem reports.
882 *
883 * @param fd The file descriptor.
884 * @param writer The print writer to dump the state to.
885 * @param args Optional dump arguments.
886 */
887 @Override
888 protected void dump(FileDescriptor fd, final PrintWriter writer, String[] args) {
889 if (mContext.checkCallingOrSelfPermission(
890 android.Manifest.permission.DUMP)
891 != PackageManager.PERMISSION_GRANTED) {
892 writer.println("Permission Denial: can't dump TelecomService " +
893 "from from pid=" + Binder.getCallingPid() + ", uid=" +
894 Binder.getCallingUid());
895 return;
896 }
897
898 final IndentingPrintWriter pw = new IndentingPrintWriter(writer, " ");
Ihab Awad8de76912015-02-17 12:25:52 -0800899 if (mCallsManager != null) {
Ihab Awad78a5e6b2015-02-06 10:13:05 -0800900 pw.println("CallsManager: ");
Tyler Gunn47689862014-12-17 17:10:28 -0800901 pw.increaseIndent();
Ihab Awad8de76912015-02-17 12:25:52 -0800902 mCallsManager.dump(pw);
Tyler Gunn47689862014-12-17 17:10:28 -0800903 pw.decreaseIndent();
904
Ihab Awad78a5e6b2015-02-06 10:13:05 -0800905 pw.println("PhoneAccountRegistrar: ");
Tyler Gunn47689862014-12-17 17:10:28 -0800906 pw.increaseIndent();
Ihab Awad8d5d9dd2015-03-12 11:11:06 -0700907 mPhoneAccountRegistrar.dump(pw);
Tyler Gunn47689862014-12-17 17:10:28 -0800908 pw.decreaseIndent();
909 }
Santos Cordon2685dab2015-04-17 17:12:09 -0700910
911 Log.dumpCallEvents(pw);
Tyler Gunn47689862014-12-17 17:10:28 -0800912 }
Ihab Awad8d5d9dd2015-03-12 11:11:06 -0700913 };
914
915 private Context mContext;
916 private AppOpsManager mAppOpsManager;
917 private UserManager mUserManager;
918 private PackageManager mPackageManager;
919 private CallsManager mCallsManager;
920 private final PhoneAccountRegistrar mPhoneAccountRegistrar;
921 private final TelecomSystem.SyncRoot mLock;
922
923 public TelecomServiceImpl(
924 Context context,
925 CallsManager callsManager,
926 PhoneAccountRegistrar phoneAccountRegistrar,
927 TelecomSystem.SyncRoot lock) {
928 mContext = context;
929 mAppOpsManager = (AppOpsManager) mContext.getSystemService(Context.APP_OPS_SERVICE);
930
931 mUserManager = (UserManager) mContext.getSystemService(Context.USER_SERVICE);
932 mPackageManager = mContext.getPackageManager();
933
934 mCallsManager = callsManager;
935 mLock = lock;
936 mPhoneAccountRegistrar = phoneAccountRegistrar;
937 }
938
Ihab Awadaa383cc2015-03-22 22:12:28 -0700939 public ITelecomService.Stub getBinder() {
Ihab Awad8d5d9dd2015-03-12 11:11:06 -0700940 return mBinderImpl;
Santos Cordonf987d1a2014-12-02 03:37:03 -0800941 }
942
943 //
944 // Supporting methods for the ITelecomService interface implementation.
945 //
946
947 private boolean isVisibleToCaller(PhoneAccountHandle accountHandle) {
948 if (accountHandle == null) {
949 return false;
950 }
Santos Cordon6a212642015-05-08 16:35:23 -0700951 return isVisibleToCaller(mPhoneAccountRegistrar.getPhoneAccount(accountHandle));
Santos Cordonf987d1a2014-12-02 03:37:03 -0800952 }
953
954 private boolean isVisibleToCaller(PhoneAccount account) {
955 if (account == null) {
956 return false;
957 }
958
959 // If this PhoneAccount has CAPABILITY_MULTI_USER, it should be visible to all users and
960 // all profiles. Only Telephony and SIP accounts should have this capability.
961 if (account.hasCapabilities(PhoneAccount.CAPABILITY_MULTI_USER)) {
962 return true;
963 }
964
965 UserHandle phoneAccountUserHandle = account.getAccountHandle().getUserHandle();
966 if (phoneAccountUserHandle == null) {
967 return false;
968 }
969
Sailesh Nepal91fc8092015-02-14 15:44:55 -0800970 if (phoneAccountUserHandle.equals(Binder.getCallingUserHandle())) {
971 return true;
972 }
973
Santos Cordonf987d1a2014-12-02 03:37:03 -0800974 List<UserHandle> profileUserHandles;
Sailesh Nepal91fc8092015-02-14 15:44:55 -0800975 if (UserHandle.getCallingUserId() == UserHandle.USER_OWNER) {
Santos Cordonf987d1a2014-12-02 03:37:03 -0800976 profileUserHandles = mUserManager.getUserProfiles();
977 } else {
978 // Otherwise, it has to be owned by the current caller's profile.
979 profileUserHandles = new ArrayList<>(1);
980 profileUserHandles.add(Binder.getCallingUserHandle());
981 }
982
983 return profileUserHandles.contains(phoneAccountUserHandle);
984 }
985
986 /**
987 * Given a list of {@link PhoneAccountHandle}s, filter them to the ones that the calling
988 * user can see.
989 *
990 * @param phoneAccountHandles Unfiltered list of account handles.
991 *
992 * @return {@link PhoneAccountHandle}s visible to the calling user and its profiles.
993 */
994 private List<PhoneAccountHandle> filterForAccountsVisibleToCaller(
995 List<PhoneAccountHandle> phoneAccountHandles) {
996 List<PhoneAccountHandle> profilePhoneAccountHandles =
997 new ArrayList<>(phoneAccountHandles.size());
998 for (PhoneAccountHandle phoneAccountHandle : phoneAccountHandles) {
999 if (isVisibleToCaller(phoneAccountHandle)) {
1000 profilePhoneAccountHandles.add(phoneAccountHandle);
1001 }
1002 }
1003 return profilePhoneAccountHandles;
1004 }
1005
1006 private boolean isCallerSystemApp() {
1007 int uid = Binder.getCallingUid();
1008 String[] packages = mPackageManager.getPackagesForUid(uid);
1009 for (String packageName : packages) {
1010 if (isPackageSystemApp(packageName)) {
1011 return true;
1012 }
1013 }
1014 return false;
1015 }
1016
1017 private boolean isPackageSystemApp(String packageName) {
1018 try {
1019 ApplicationInfo applicationInfo = mPackageManager.getApplicationInfo(packageName,
1020 PackageManager.GET_META_DATA);
1021 if ((applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0) {
1022 return true;
1023 }
1024 } catch (PackageManager.NameNotFoundException e) {
1025 }
1026 return false;
1027 }
1028
1029 private void acceptRingingCallInternal() {
Ihab Awad8de76912015-02-17 12:25:52 -08001030 Call call = mCallsManager.getFirstCallWithState(CallState.RINGING);
Santos Cordonf987d1a2014-12-02 03:37:03 -08001031 if (call != null) {
1032 call.answer(call.getVideoState());
1033 }
1034 }
1035
1036 private boolean endCallInternal() {
1037 // Always operate on the foreground call if one exists, otherwise get the first call in
1038 // priority order by call-state.
Ihab Awad8de76912015-02-17 12:25:52 -08001039 Call call = mCallsManager.getForegroundCall();
Santos Cordonf987d1a2014-12-02 03:37:03 -08001040 if (call == null) {
Ihab Awad8de76912015-02-17 12:25:52 -08001041 call = mCallsManager.getFirstCallWithState(
Santos Cordonf987d1a2014-12-02 03:37:03 -08001042 CallState.ACTIVE,
1043 CallState.DIALING,
1044 CallState.RINGING,
1045 CallState.ON_HOLD);
1046 }
1047
1048 if (call != null) {
1049 if (call.getState() == CallState.RINGING) {
1050 call.reject(false /* rejectWithMessage */, null);
1051 } else {
1052 call.disconnect();
1053 }
1054 return true;
1055 }
1056
1057 return false;
1058 }
1059
1060 private void enforcePhoneAccountModificationForPackage(String packageName) {
1061 // TODO: Use a new telecomm permission for this instead of reusing modify.
1062
Yorke Leecb0bd8a2015-05-18 11:57:14 -07001063 int result = mContext.checkCallingOrSelfPermission(MODIFY_PHONE_STATE);
Santos Cordonf987d1a2014-12-02 03:37:03 -08001064
1065 // Callers with MODIFY_PHONE_STATE can use the PhoneAccount mechanism to implement
1066 // built-in behavior even when PhoneAccounts are not exposed as a third-part API. They
1067 // may also modify PhoneAccounts on behalf of any 'packageName'.
1068
1069 if (result != PackageManager.PERMISSION_GRANTED) {
1070 // Other callers are only allowed to modify PhoneAccounts if the relevant system
1071 // feature is enabled ...
1072 enforceConnectionServiceFeature();
1073 // ... and the PhoneAccounts they refer to are for their own package.
1074 enforceCallingPackage(packageName);
1075 }
1076 }
1077
Yorke Leecb0bd8a2015-05-18 11:57:14 -07001078 private void enforcePermissionOrPrivilegedDialer(String permission, String packageName) {
Yorke Lee53101962015-04-29 16:25:29 -07001079 if (!isPrivilegedDialerCalling(packageName)) {
1080 try {
Yorke Leecb0bd8a2015-05-18 11:57:14 -07001081 enforcePermission(permission);
Yorke Lee53101962015-04-29 16:25:29 -07001082 } catch (SecurityException e) {
Yorke Leecb0bd8a2015-05-18 11:57:14 -07001083 Log.e(this, e, "Caller must be the default or system dialer, or have the permission"
1084 + " %s to perform this operation.", permission);
Yorke Lee53101962015-04-29 16:25:29 -07001085 throw e;
1086 }
Santos Cordonf987d1a2014-12-02 03:37:03 -08001087 }
1088 }
1089
1090 private void enforceCallingPackage(String packageName) {
1091 mAppOpsManager.checkPackage(Binder.getCallingUid(), packageName);
1092 }
1093
1094 private void enforceConnectionServiceFeature() {
1095 enforceFeature(PackageManager.FEATURE_CONNECTION_SERVICE);
1096 }
1097
1098 private void enforceRegisterCallProviderPermission() {
Yorke Leecb0bd8a2015-05-18 11:57:14 -07001099 enforcePermission(REGISTER_CALL_PROVIDER);
Santos Cordonf987d1a2014-12-02 03:37:03 -08001100 }
1101
1102 private void enforceRegisterSimSubscriptionPermission() {
Yorke Leecb0bd8a2015-05-18 11:57:14 -07001103 enforcePermission(REGISTER_SIM_SUBSCRIPTION);
Santos Cordonf987d1a2014-12-02 03:37:03 -08001104 }
1105
1106 private void enforceRegisterConnectionManagerPermission() {
Yorke Leecb0bd8a2015-05-18 11:57:14 -07001107 enforcePermission(REGISTER_CONNECTION_MANAGER);
Santos Cordonf987d1a2014-12-02 03:37:03 -08001108 }
1109
Santos Cordonf987d1a2014-12-02 03:37:03 -08001110 private void enforceModifyPermission() {
Yorke Leecb0bd8a2015-05-18 11:57:14 -07001111 enforcePermission(MODIFY_PHONE_STATE);
Santos Cordonf987d1a2014-12-02 03:37:03 -08001112 }
1113
1114 private void enforcePermission(String permission) {
1115 mContext.enforceCallingOrSelfPermission(permission, null);
1116 }
1117
1118 private void enforceRegisterMultiUser() {
1119 if (!isCallerSystemApp()) {
1120 throw new SecurityException("CAPABILITY_MULTI_USER is only available to system apps.");
1121 }
1122 }
1123
1124 private void enforceUserHandleMatchesCaller(PhoneAccountHandle accountHandle) {
1125 if (!Binder.getCallingUserHandle().equals(accountHandle.getUserHandle())) {
1126 throw new SecurityException("Calling UserHandle does not match PhoneAccountHandle's");
1127 }
1128 }
1129
1130 private void enforceFeature(String feature) {
1131 PackageManager pm = mContext.getPackageManager();
1132 if (!pm.hasSystemFeature(feature)) {
1133 throw new UnsupportedOperationException(
1134 "System does not support feature " + feature);
1135 }
1136 }
1137
Svet Ganov38f1a4d2015-04-17 15:28:03 -07001138 private boolean canReadPhoneState(String callingPackage, String message) {
Yorke Lee57138a62015-05-18 18:18:08 -07001139 // The system/default dialer can always read phone state - so that emergency calls will
1140 // still work.
1141 if (isPrivilegedDialerCalling(callingPackage)) {
1142 return true;
1143 }
1144
Svet Ganov09611182015-04-16 12:29:01 -07001145 // Accessing phone state is gated by a special permission.
Yorke Leecb0bd8a2015-05-18 11:57:14 -07001146 mContext.enforceCallingOrSelfPermission(READ_PHONE_STATE, message);
Svet Ganov09611182015-04-16 12:29:01 -07001147
1148 // Some apps that have the permission can be restricted via app ops.
1149 return mAppOpsManager.noteOp(AppOpsManager.OP_READ_PHONE_STATE,
1150 Binder.getCallingUid(), callingPackage) == AppOpsManager.MODE_ALLOWED;
1151 }
1152
Yorke Leea3a3adc2015-04-23 12:49:01 -07001153 private boolean canCallPhone(String callingPackage, String message) {
Yorke Lee57138a62015-05-18 18:18:08 -07001154 // The system/default dialer can always read phone state - so that emergency calls will
1155 // still work.
1156 if (isPrivilegedDialerCalling(callingPackage)) {
1157 return true;
1158 }
1159
Yorke Leea3a3adc2015-04-23 12:49:01 -07001160 // Accessing phone state is gated by a special permission.
Yorke Leecb0bd8a2015-05-18 11:57:14 -07001161 mContext.enforceCallingOrSelfPermission(CALL_PHONE, message);
Yorke Leea3a3adc2015-04-23 12:49:01 -07001162
1163 // Some apps that have the permission can be restricted via app ops.
1164 return mAppOpsManager.noteOp(AppOpsManager.OP_CALL_PHONE,
1165 Binder.getCallingUid(), callingPackage) == AppOpsManager.MODE_ALLOWED;
1166 }
1167
Sailesh Nepal2a98c972015-03-04 15:43:15 -08001168 private boolean isCallerSimCallManager() {
Etan Cohenb600a5f2015-03-06 17:37:30 -08001169 PhoneAccountHandle accountHandle = TelecomSystem.getInstance().getPhoneAccountRegistrar()
1170 .getSimCallManager();
Sailesh Nepal2a98c972015-03-04 15:43:15 -08001171 if (accountHandle != null) {
1172 try {
1173 mAppOpsManager.checkPackage(
1174 Binder.getCallingUid(), accountHandle.getComponentName().getPackageName());
1175 return true;
1176 } catch (SecurityException e) {
1177 }
1178 }
1179 return false;
1180 }
1181
Yorke Lee53101962015-04-29 16:25:29 -07001182 private boolean isPrivilegedDialerCalling(String callingPackage) {
1183 mAppOpsManager.checkPackage(Binder.getCallingUid(), callingPackage);
1184 return DefaultDialerManager.isDefaultOrSystemDialer(mContext, callingPackage);
Santos Cordonf987d1a2014-12-02 03:37:03 -08001185 }
1186
1187 private TelephonyManager getTelephonyManager() {
1188 return (TelephonyManager)mContext.getSystemService(Context.TELEPHONY_SERVICE);
1189 }
Santos Cordonf987d1a2014-12-02 03:37:03 -08001190}