TelecomServiceImpl.java revision 5dc42ee62c21ee81d51a411a0cfb61653fdf2858
1/*
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
19import 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_SIM_SUBSCRIPTION;
23import static android.Manifest.permission.WRITE_SECURE_SETTINGS;
24
25import android.app.ActivityManager;
26import android.app.AppOpsManager;
27import android.content.ComponentName;
28import android.content.Context;
29import android.content.Intent;
30import android.content.pm.ApplicationInfo;
31import android.content.pm.PackageManager;
32import android.content.res.Resources;
33import android.net.Uri;
34import android.os.Binder;
35import android.os.Bundle;
36import android.os.IBinder;
37import android.os.UserHandle;
38import android.os.UserManager;
39import android.telecom.DefaultDialerManager;
40import android.telecom.PhoneAccount;
41import android.telecom.PhoneAccountHandle;
42import android.telecom.TelecomManager;
43import android.telephony.SubscriptionManager;
44import android.telephony.TelephonyManager;
45import android.text.TextUtils;
46
47// TODO: Needed for move to system service: import com.android.internal.R;
48import com.android.internal.telecom.ITelecomService;
49import com.android.internal.util.IndentingPrintWriter;
50import com.android.server.telecom.components.UserCallIntentProcessor;
51
52import java.io.FileDescriptor;
53import java.io.PrintWriter;
54import java.util.ArrayList;
55import java.util.Collections;
56import java.util.List;
57
58/**
59 * Implementation of the ITelecom interface.
60 */
61public class TelecomServiceImpl {
62    private static final String PERMISSION_PROCESS_PHONE_ACCOUNT_REGISTRATION =
63            "android.permission.PROCESS_PHONE_ACCOUNT_REGISTRATION";
64
65    private final ITelecomService.Stub mBinderImpl = new ITelecomService.Stub() {
66        @Override
67        public PhoneAccountHandle getDefaultOutgoingPhoneAccount(String uriScheme,
68                String callingPackage) {
69            synchronized (mLock) {
70                if (!canReadPhoneState(callingPackage, "getDefaultOutgoingPhoneAccount")) {
71                    return null;
72                }
73
74                long token = Binder.clearCallingIdentity();
75                try {
76                    PhoneAccountHandle defaultOutgoingPhoneAccount =
77                            mPhoneAccountRegistrar.getOutgoingPhoneAccountForScheme(uriScheme);
78                    // Make sure that the calling user can see this phone account.
79                    // TODO: Does this isVisible check actually work considering we are clearing
80                    // the calling identity?
81                    if (defaultOutgoingPhoneAccount != null
82                            && !isVisibleToCaller(defaultOutgoingPhoneAccount)) {
83                        Log.w(this, "No account found for the calling user");
84                        return null;
85                    }
86                    return defaultOutgoingPhoneAccount;
87                } catch (Exception e) {
88                    Log.e(this, e, "getDefaultOutgoingPhoneAccount");
89                    throw e;
90                } finally {
91                    Binder.restoreCallingIdentity(token);
92                }
93            }
94        }
95
96        @Override
97        public PhoneAccountHandle getUserSelectedOutgoingPhoneAccount() {
98            synchronized (mLock) {
99                try {
100                    PhoneAccountHandle userSelectedOutgoingPhoneAccount =
101                            mPhoneAccountRegistrar.getUserSelectedOutgoingPhoneAccount();
102                    // Make sure that the calling user can see this phone account.
103                    if (!isVisibleToCaller(userSelectedOutgoingPhoneAccount)) {
104                        Log.w(this, "No account found for the calling user");
105                        return null;
106                    }
107                    return userSelectedOutgoingPhoneAccount;
108                } catch (Exception e) {
109                    Log.e(this, e, "getUserSelectedOutgoingPhoneAccount");
110                    throw e;
111                }
112            }
113        }
114
115        @Override
116        public void setUserSelectedOutgoingPhoneAccount(PhoneAccountHandle accountHandle) {
117            synchronized (mLock) {
118                enforceModifyPermission();
119
120                long token = Binder.clearCallingIdentity();
121                try {
122                    mPhoneAccountRegistrar.setUserSelectedOutgoingPhoneAccount(accountHandle);
123                } catch (Exception e) {
124                    Log.e(this, e, "setUserSelectedOutgoingPhoneAccount");
125                    throw e;
126                } finally {
127                    Binder.restoreCallingIdentity(token);
128                }
129            }
130        }
131
132        @Override
133        public List<PhoneAccountHandle> getCallCapablePhoneAccounts(
134                boolean includeDisabledAccounts, String callingPackage) {
135            if (!canReadPhoneState(callingPackage, "getDefaultOutgoingPhoneAccount")) {
136                return Collections.emptyList();
137            }
138
139            synchronized (mLock) {
140                long token = Binder.clearCallingIdentity();
141                try {
142                    // TODO: Does this isVisible check actually work considering we are clearing
143                    // the calling identity?
144                    return filterForAccountsVisibleToCaller(
145                            mPhoneAccountRegistrar.getCallCapablePhoneAccounts(
146                                    null, includeDisabledAccounts));
147                } catch (Exception e) {
148                    Log.e(this, e, "getCallCapablePhoneAccounts");
149                    throw e;
150                } finally {
151                    Binder.restoreCallingIdentity(token);
152                }
153            }
154        }
155
156        @Override
157        public List<PhoneAccountHandle> getPhoneAccountsSupportingScheme(String uriScheme,
158                String callingPackage) {
159            synchronized (mLock) {
160                if (!canReadPhoneState(callingPackage, "getPhoneAccountsSupportingScheme")) {
161                    return Collections.emptyList();
162                }
163
164                long token = Binder.clearCallingIdentity();
165                try {
166                    // TODO: Does this isVisible check actually work considering we are clearing
167                    // the calling identity?
168                    return filterForAccountsVisibleToCaller(
169                            mPhoneAccountRegistrar.getCallCapablePhoneAccounts(uriScheme, false));
170                } catch (Exception e) {
171                    Log.e(this, e, "getPhoneAccountsSupportingScheme %s", uriScheme);
172                    throw e;
173                } finally {
174                    Binder.restoreCallingIdentity(token);
175                }
176            }
177        }
178
179        @Override
180        public List<PhoneAccountHandle> getPhoneAccountsForPackage(String packageName) {
181            synchronized (mLock) {
182                try {
183                    return filterForAccountsVisibleToCaller(
184                            mPhoneAccountRegistrar.getPhoneAccountsForPackage(packageName));
185                } catch (Exception e) {
186                    Log.e(this, e, "getPhoneAccountsForPackage %s", packageName);
187                    throw e;
188                }
189            }
190        }
191
192        @Override
193        public PhoneAccount getPhoneAccount(PhoneAccountHandle accountHandle) {
194            synchronized (mLock) {
195                try {
196                    if (!isVisibleToCaller(accountHandle)) {
197                        Log.d(this, "%s is not visible for the calling user [gPA]", accountHandle);
198                        return null;
199                    }
200                    // TODO: Do we really want to return for *any* user?
201                    return mPhoneAccountRegistrar.getPhoneAccount(accountHandle);
202                } catch (Exception e) {
203                    Log.e(this, e, "getPhoneAccount %s", accountHandle);
204                    throw e;
205                }
206            }
207        }
208
209        @Override
210        public int getAllPhoneAccountsCount() {
211            synchronized (mLock) {
212                try {
213                    // This list is pre-filtered for the calling user.
214                    return getAllPhoneAccounts().size();
215                } catch (Exception e) {
216                    Log.e(this, e, "getAllPhoneAccountsCount");
217                    throw e;
218                }
219            }
220        }
221
222        @Override
223        public List<PhoneAccount> getAllPhoneAccounts() {
224            synchronized (mLock) {
225                try {
226                    List<PhoneAccount> allPhoneAccounts = mPhoneAccountRegistrar
227                            .getAllPhoneAccounts();
228                    List<PhoneAccount> profilePhoneAccounts = new ArrayList<>(
229                            allPhoneAccounts.size());
230                    for (PhoneAccount phoneAccount : profilePhoneAccounts) {
231                        if (isVisibleToCaller(phoneAccount)) {
232                            profilePhoneAccounts.add(phoneAccount);
233                        }
234                    }
235                    return profilePhoneAccounts;
236                } catch (Exception e) {
237                    Log.e(this, e, "getAllPhoneAccounts");
238                    throw e;
239                }
240            }
241        }
242
243        @Override
244        public List<PhoneAccountHandle> getAllPhoneAccountHandles() {
245            synchronized (mLock) {
246                try {
247                    return filterForAccountsVisibleToCaller(
248                            mPhoneAccountRegistrar.getAllPhoneAccountHandles());
249                } catch (Exception e) {
250                    Log.e(this, e, "getAllPhoneAccounts");
251                    throw e;
252                }
253            }
254        }
255
256        @Override
257        public PhoneAccountHandle getSimCallManager() {
258            synchronized (mLock) {
259                try {
260                    PhoneAccountHandle accountHandle = null;
261
262                    long token = Binder.clearCallingIdentity();
263                    try {
264                        accountHandle = mPhoneAccountRegistrar.getSimCallManager();
265                    } finally {
266                        // We restore early so that isVisibleToCaller invocation below uses the
267                        // right user context.
268                        Binder.restoreCallingIdentity(token);
269                    }
270
271                    if (!isVisibleToCaller(accountHandle)) {
272                        Log.d(this, "%s is not visible for the calling user [gsCM]", accountHandle);
273                        return null;
274                    }
275                    return accountHandle;
276                } catch (Exception e) {
277                    Log.e(this, e, "getSimCallManager");
278                    throw e;
279                }
280            }
281        }
282
283        @Override
284        public void registerPhoneAccount(PhoneAccount account) {
285            synchronized (mLock) {
286                if (!mContext.getApplicationContext().getResources().getBoolean(
287                        com.android.internal.R.bool.config_voice_capable)) {
288                    Log.w(this, "registerPhoneAccount not allowed on non-voice capable device.");
289                    return;
290                }
291                try {
292                    enforcePhoneAccountModificationForPackage(
293                            account.getAccountHandle().getComponentName().getPackageName());
294                    if (account.hasCapabilities(PhoneAccount.CAPABILITY_SIM_SUBSCRIPTION)) {
295                        enforceRegisterSimSubscriptionPermission();
296                    }
297                    if (account.hasCapabilities(PhoneAccount.CAPABILITY_MULTI_USER)) {
298                        enforceRegisterMultiUser();
299                    }
300                    enforceUserHandleMatchesCaller(account.getAccountHandle());
301
302                    mPhoneAccountRegistrar.registerPhoneAccount(account);
303
304                    // Broadcast an intent indicating the phone account which was registered.
305                    long token = Binder.clearCallingIdentity();
306                    try {
307                        Intent intent = new Intent(TelecomManager.ACTION_PHONE_ACCOUNT_REGISTERED);
308                        intent.putExtra(TelecomManager.EXTRA_PHONE_ACCOUNT_HANDLE,
309                                account.getAccountHandle());
310                        Log.i(this, "Sending phone-account intent as user");
311                        mContext.sendBroadcastAsUser(intent, UserHandle.ALL,
312                                PERMISSION_PROCESS_PHONE_ACCOUNT_REGISTRATION);
313                    } finally {
314                        Binder.restoreCallingIdentity(token);
315                    }
316                } catch (Exception e) {
317                    Log.e(this, e, "registerPhoneAccount %s", account);
318                    throw e;
319                }
320            }
321        }
322
323        @Override
324        public void unregisterPhoneAccount(PhoneAccountHandle accountHandle) {
325            synchronized (mLock) {
326                try {
327                    enforcePhoneAccountModificationForPackage(
328                            accountHandle.getComponentName().getPackageName());
329                    enforceUserHandleMatchesCaller(accountHandle);
330                    mPhoneAccountRegistrar.unregisterPhoneAccount(accountHandle);
331                } catch (Exception e) {
332                    Log.e(this, e, "unregisterPhoneAccount %s", accountHandle);
333                    throw e;
334                }
335            }
336        }
337
338        @Override
339        public void clearAccounts(String packageName) {
340            synchronized (mLock) {
341                try {
342                    enforcePhoneAccountModificationForPackage(packageName);
343                    mPhoneAccountRegistrar
344                            .clearAccounts(packageName, Binder.getCallingUserHandle());
345                } catch (Exception e) {
346                    Log.e(this, e, "clearAccounts %s", packageName);
347                    throw e;
348                }
349            }
350        }
351
352        /**
353         * @see android.telecom.TelecomManager#isVoiceMailNumber
354         */
355        @Override
356        public boolean isVoiceMailNumber(PhoneAccountHandle accountHandle, String number,
357                String callingPackage) {
358            synchronized (mLock) {
359                if (!canReadPhoneState(callingPackage, "isVoiceMailNumber")) {
360                    return false;
361                }
362
363                if (!isVisibleToCaller(accountHandle)) {
364                    Log.d(this, "%s is not visible for the calling user [iVMN]", accountHandle);
365                    return false;
366                }
367
368                long token = Binder.clearCallingIdentity();
369                try {
370                    return mPhoneAccountRegistrar.isVoiceMailNumber(accountHandle, number);
371                } catch (Exception e) {
372                    Log.e(this, e, "getSubscriptionIdForPhoneAccount");
373                    throw e;
374                } finally {
375                    Binder.restoreCallingIdentity(token);
376                }
377            }
378        }
379
380        /**
381         * @see android.telecom.TelecomManager#getVoiceMailNumber
382         */
383        @Override
384        public String getVoiceMailNumber(PhoneAccountHandle accountHandle, String callingPackage) {
385            synchronized (mLock) {
386                if (!canReadPhoneState(callingPackage, "getVoiceMailNumber")) {
387                    return null;
388                }
389
390                try {
391                    if (!isVisibleToCaller(accountHandle)) {
392                        Log.d(this, "%s is not visible for the calling user [gVMN]", accountHandle);
393                        return null;
394                    }
395
396                    int subId = SubscriptionManager.getDefaultVoiceSubId();
397                    if (accountHandle != null) {
398                        subId = mPhoneAccountRegistrar
399                                .getSubscriptionIdForPhoneAccount(accountHandle);
400                    }
401                    return getTelephonyManager().getVoiceMailNumber(subId);
402                } catch (Exception e) {
403                    Log.e(this, e, "getSubscriptionIdForPhoneAccount");
404                    throw e;
405                }
406            }
407        }
408
409        /**
410         * @see android.telecom.TelecomManager#getLine1Number
411         */
412        @Override
413        public String getLine1Number(PhoneAccountHandle accountHandle, String callingPackage) {
414            if (!canReadPhoneState(callingPackage, "getLine1Number")) {
415                return null;
416            }
417
418            synchronized (mLock) {
419                if (!isVisibleToCaller(accountHandle)) {
420                    Log.d(this, "%s is not visible for the calling user [gL1N]", accountHandle);
421                    return null;
422                }
423
424                long token = Binder.clearCallingIdentity();
425                try {
426                    int subId =
427                            mPhoneAccountRegistrar.getSubscriptionIdForPhoneAccount(accountHandle);
428                    return getTelephonyManager().getLine1NumberForSubscriber(subId);
429                } catch (Exception e) {
430                    Log.e(this, e, "getSubscriptionIdForPhoneAccount");
431                    throw e;
432                } finally {
433                    Binder.restoreCallingIdentity(token);
434                }
435            }
436        }
437
438        /**
439         * @see android.telecom.TelecomManager#silenceRinger
440         */
441        @Override
442        public void silenceRinger(String callingPackage) {
443            synchronized (mLock) {
444                enforcePermissionOrPrivilegedDialer(MODIFY_PHONE_STATE, callingPackage);
445
446                long token = Binder.clearCallingIdentity();
447                try {
448                    Log.i(this, "Silence Ringer requested by %s", callingPackage);
449                    mCallsManager.getRinger().silence();
450                } finally {
451                    Binder.restoreCallingIdentity(token);
452                }
453            }
454        }
455
456        /**
457         * @see android.telecom.TelecomManager#getDefaultPhoneApp
458         * @deprecated - Use {@link android.telecom.TelecomManager#getDefaultDialerPackage()}
459         *         instead.
460         */
461        @Override
462        public ComponentName getDefaultPhoneApp() {
463            // No need to synchronize
464            Resources resources = mContext.getResources();
465            return new ComponentName(
466                    resources.getString(R.string.ui_default_package),
467                    resources.getString(R.string.dialer_default_class));
468        }
469
470        /**
471         * @return the package name of the current user-selected default dialer. If no default
472         *         has been selected, the package name of the system dialer is returned. If
473         *         neither exists, then {@code null} is returned.
474         * @see android.telecom.TelecomManager#getDefaultDialerPackage
475         */
476        @Override
477        public String getDefaultDialerPackage() {
478            final long token = Binder.clearCallingIdentity();
479            try {
480                return DefaultDialerManager.getDefaultDialerApplication(mContext);
481            } finally {
482                Binder.restoreCallingIdentity(token);
483            }
484        }
485
486        /**
487         * @see android.telecom.TelecomManager#getSystemDialerPackage
488         */
489        @Override
490        public String getSystemDialerPackage() {
491            return mContext.getResources().getString(R.string.ui_default_package);
492        }
493
494        /**
495         * @see android.telecom.TelecomManager#isInCall
496         */
497        @Override
498        public boolean isInCall(String callingPackage) {
499            if (!canReadPhoneState(callingPackage, "isInCall")) {
500                return false;
501            }
502
503            synchronized (mLock) {
504                final int callState = mCallsManager.getCallState();
505                return callState == TelephonyManager.CALL_STATE_OFFHOOK
506                        || callState == TelephonyManager.CALL_STATE_RINGING;
507            }
508        }
509
510        /**
511         * @see android.telecom.TelecomManager#isRinging
512         */
513        @Override
514        public boolean isRinging(String callingPackage) {
515            if (!canReadPhoneState(callingPackage, "isRinging")) {
516                return false;
517            }
518
519            synchronized (mLock) {
520                return mCallsManager.getCallState() == TelephonyManager.CALL_STATE_RINGING;
521            }
522        }
523
524        /**
525         * @see TelecomManager#getCallState
526         */
527        @Override
528        public int getCallState() {
529            synchronized (mLock) {
530                return mCallsManager.getCallState();
531            }
532        }
533
534        /**
535         * @see android.telecom.TelecomManager#endCall
536         */
537        @Override
538        public boolean endCall() {
539            synchronized (mLock) {
540                enforceModifyPermission();
541
542                long token = Binder.clearCallingIdentity();
543                try {
544                    return endCallInternal();
545                } finally {
546                    Binder.restoreCallingIdentity(token);
547                }
548            }
549        }
550
551        /**
552         * @see android.telecom.TelecomManager#acceptRingingCall
553         */
554        @Override
555        public void acceptRingingCall() {
556            synchronized (mLock) {
557                enforceModifyPermission();
558
559                long token = Binder.clearCallingIdentity();
560                try {
561                    acceptRingingCallInternal();
562                } finally {
563                    Binder.restoreCallingIdentity(token);
564                }
565            }
566        }
567
568        /**
569         * @see android.telecom.TelecomManager#showInCallScreen
570         */
571        @Override
572        public void showInCallScreen(boolean showDialpad, String callingPackage) {
573            if (!canReadPhoneState(callingPackage, "showInCallScreen")) {
574                return;
575            }
576
577            synchronized (mLock) {
578
579                long token = Binder.clearCallingIdentity();
580                try {
581                    mCallsManager.getInCallController().bringToForeground(showDialpad);
582                } finally {
583                    Binder.restoreCallingIdentity(token);
584                }
585            }
586        }
587
588        /**
589         * @see android.telecom.TelecomManager#cancelMissedCallsNotification
590         */
591        @Override
592        public void cancelMissedCallsNotification(String callingPackage) {
593            synchronized (mLock) {
594                enforcePermissionOrPrivilegedDialer(MODIFY_PHONE_STATE, callingPackage);
595                long token = Binder.clearCallingIdentity();
596                try {
597                    mCallsManager.getMissedCallNotifier().clearMissedCalls();
598                } finally {
599                    Binder.restoreCallingIdentity(token);
600                }
601            }
602        }
603
604        /**
605         * @see android.telecom.TelecomManager#handleMmi
606         */
607        @Override
608        public boolean handlePinMmi(String dialString, String callingPackage) {
609            synchronized (mLock) {
610                enforcePermissionOrPrivilegedDialer(MODIFY_PHONE_STATE, callingPackage);
611
612                // Switch identity so that TelephonyManager checks Telecom's permissions instead.
613                long token = Binder.clearCallingIdentity();
614                boolean retval = false;
615                try {
616                    retval = getTelephonyManager().handlePinMmi(dialString);
617                } finally {
618                    Binder.restoreCallingIdentity(token);
619                }
620
621                return retval;
622            }
623        }
624
625        /**
626         * @see android.telecom.TelecomManager#handleMmi
627         */
628        @Override
629        public boolean handlePinMmiForPhoneAccount(
630                PhoneAccountHandle accountHandle,
631                String dialString,
632                String callingPackage) {
633            synchronized (mLock) {
634                enforcePermissionOrPrivilegedDialer(MODIFY_PHONE_STATE, callingPackage);
635
636                if (!isVisibleToCaller(accountHandle)) {
637                    Log.d(this, "%s is not visible for the calling user [hMMI]", accountHandle);
638                    return false;
639                }
640
641                // Switch identity so that TelephonyManager checks Telecom's permissions instead.
642                long token = Binder.clearCallingIdentity();
643                boolean retval = false;
644                try {
645                    int subId = mPhoneAccountRegistrar
646                            .getSubscriptionIdForPhoneAccount(accountHandle);
647                    retval = getTelephonyManager().handlePinMmiForSubscriber(subId, dialString);
648                } finally {
649                    Binder.restoreCallingIdentity(token);
650                }
651
652                return retval;
653            }
654        }
655
656        /**
657         * @see android.telecom.TelecomManager#getAdnUriForPhoneAccount
658         */
659        @Override
660        public Uri getAdnUriForPhoneAccount(PhoneAccountHandle accountHandle,
661                String callingPackage) {
662            synchronized (mLock) {
663                enforcePermissionOrPrivilegedDialer(MODIFY_PHONE_STATE, callingPackage);
664
665                if (!isVisibleToCaller(accountHandle)) {
666                    Log.d(this, "%s is not visible for the calling user [gA4PA]", accountHandle);
667                    return null;
668                }
669
670                // Switch identity so that TelephonyManager checks Telecom's permissions instead.
671                long token = Binder.clearCallingIdentity();
672                String retval = "content://icc/adn/";
673                try {
674                    long subId = mPhoneAccountRegistrar
675                            .getSubscriptionIdForPhoneAccount(accountHandle);
676                    retval = retval + "subId/" + subId;
677                } finally {
678                    Binder.restoreCallingIdentity(token);
679                }
680
681                return Uri.parse(retval);
682            }
683        }
684
685        /**
686         * @see android.telecom.TelecomManager#isTtySupported
687         */
688        @Override
689        public boolean isTtySupported(String callingPackage) {
690            if (!canReadPhoneState(callingPackage, "hasVoiceMailNumber")) {
691                return false;
692            }
693
694            synchronized (mLock) {
695                return mCallsManager.isTtySupported();
696            }
697        }
698
699        /**
700         * @see android.telecom.TelecomManager#getCurrentTtyMode
701         */
702        @Override
703        public int getCurrentTtyMode(String callingPackage) {
704            if (!canReadPhoneState(callingPackage, "getCurrentTtyMode")) {
705                return TelecomManager.TTY_MODE_OFF;
706            }
707
708            synchronized (mLock) {
709                return mCallsManager.getCurrentTtyMode();
710            }
711        }
712
713        /**
714         * @see android.telecom.TelecomManager#addNewIncomingCall
715         */
716        @Override
717        public void addNewIncomingCall(PhoneAccountHandle phoneAccountHandle, Bundle extras) {
718            synchronized (mLock) {
719                Log.i(this, "Adding new incoming call with phoneAccountHandle %s",
720                        phoneAccountHandle);
721                if (phoneAccountHandle != null && phoneAccountHandle.getComponentName() != null) {
722                    // TODO(sail): Add unit tests for adding incoming calls from a SIM call manager.
723                    if (isCallerSimCallManager() && TelephonyUtil.isPstnComponentName(
724                            phoneAccountHandle.getComponentName())) {
725                        Log.v(this, "Allowing call manager to add incoming call with PSTN handle");
726                    } else {
727                        mAppOpsManager.checkPackage(
728                                Binder.getCallingUid(),
729                                phoneAccountHandle.getComponentName().getPackageName());
730                        // Make sure it doesn't cross the UserHandle boundary
731                        enforceUserHandleMatchesCaller(phoneAccountHandle);
732                    }
733
734                    long token = Binder.clearCallingIdentity();
735                    try {
736                        Intent intent = new Intent(TelecomManager.ACTION_INCOMING_CALL);
737                        intent.putExtra(TelecomManager.EXTRA_PHONE_ACCOUNT_HANDLE,
738                            phoneAccountHandle);
739                        intent.putExtra(CallIntentProcessor.KEY_IS_INCOMING_CALL, true);
740                        if (extras != null) {
741                            intent.putExtra(TelecomManager.EXTRA_INCOMING_CALL_EXTRAS, extras);
742                        }
743                        CallIntentProcessor.processIncomingCallIntent(mCallsManager, intent);
744                    } finally {
745                        Binder.restoreCallingIdentity(token);
746                    }
747                } else {
748                    Log.w(this,
749                            "Null phoneAccountHandle. Ignoring request to add new incoming call");
750                }
751            }
752        }
753
754        /**
755         * @see android.telecom.TelecomManager#addNewUnknownCall
756         */
757        @Override
758        public void addNewUnknownCall(PhoneAccountHandle phoneAccountHandle, Bundle extras) {
759            synchronized (mLock) {
760                if (phoneAccountHandle != null && phoneAccountHandle.getComponentName() != null) {
761                    mAppOpsManager.checkPackage(
762                            Binder.getCallingUid(),
763                            phoneAccountHandle.getComponentName().getPackageName());
764
765                    // Make sure it doesn't cross the UserHandle boundary
766                    enforceUserHandleMatchesCaller(phoneAccountHandle);
767                    long token = Binder.clearCallingIdentity();
768
769                    try {
770                        Intent intent = new Intent(TelecomManager.ACTION_NEW_UNKNOWN_CALL);
771                        intent.putExtras(extras);
772                        intent.putExtra(CallIntentProcessor.KEY_IS_UNKNOWN_CALL, true);
773                        intent.putExtra(TelecomManager.EXTRA_PHONE_ACCOUNT_HANDLE,
774                            phoneAccountHandle);
775                        CallIntentProcessor.processUnknownCallIntent(mCallsManager, intent);
776                    } finally {
777                        Binder.restoreCallingIdentity(token);
778                    }
779                } else {
780                    Log.i(this,
781                            "Null phoneAccountHandle or not initiated by Telephony. " +
782                            "Ignoring request to add new unknown call.");
783                }
784            }
785        }
786
787        /**
788         * @see android.telecom.TelecomManager#placeCall
789         */
790        @Override
791        public void placeCall(Uri handle, Bundle extras, String callingPackage) {
792            enforceCallingPackage(callingPackage);
793            if (!canCallPhone(callingPackage, "placeCall")) {
794                throw new SecurityException("Package " + callingPackage
795                        + " is not allowed to place phone calls");
796            }
797
798            final boolean hasCallAppOp = mAppOpsManager.noteOp(AppOpsManager.OP_CALL_PHONE,
799                    Binder.getCallingUid(), callingPackage) == AppOpsManager.MODE_ALLOWED;
800
801            synchronized (mLock) {
802                final UserHandle userHandle = Binder.getCallingUserHandle();
803                long token = Binder.clearCallingIdentity();
804                try {
805                    final Intent intent = new Intent(Intent.ACTION_CALL, handle);
806                    intent.putExtras(extras);
807                    new UserCallIntentProcessor(mContext, userHandle).processIntent(intent,
808                            callingPackage, hasCallAppOp);
809                } finally {
810                    Binder.restoreCallingIdentity(token);
811                }
812            }
813        }
814
815        /**
816         * @see android.telecom.TelecomManager#enablePhoneAccount
817         */
818        @Override
819        public boolean enablePhoneAccount(PhoneAccountHandle accountHandle, boolean isEnabled) {
820            enforceModifyPermission();
821            synchronized (mLock) {
822                long token  = Binder.clearCallingIdentity();
823                try {
824                    // enable/disable phone account
825                    return mPhoneAccountRegistrar.enablePhoneAccount(accountHandle, isEnabled);
826                } finally {
827                    Binder.restoreCallingIdentity(token);
828                }
829            }
830        }
831
832        @Override
833        public boolean setDefaultDialer(String packageName) {
834            enforcePermission(MODIFY_PHONE_STATE);
835            enforcePermission(WRITE_SECURE_SETTINGS);
836            synchronized (mLock) {
837                long token  = Binder.clearCallingIdentity();
838                try {
839                    final boolean result =
840                            DefaultDialerManager.setDefaultDialerApplication(mContext, packageName);
841                    if (result) {
842                        final Intent intent =
843                                new Intent(TelecomManager.ACTION_DEFAULT_DIALER_CHANGED);
844                        intent.putExtra(TelecomManager.EXTRA_CHANGE_DEFAULT_DIALER_PACKAGE_NAME,
845                                packageName);
846                        mContext.sendBroadcastAsUser(intent,
847                                new UserHandle(ActivityManager.getCurrentUser()));
848                    }
849                    return result;
850                } finally {
851                    Binder.restoreCallingIdentity(token);
852                }
853            }
854        }
855
856        /**
857         * Dumps the current state of the TelecomService.  Used when generating problem reports.
858         *
859         * @param fd The file descriptor.
860         * @param writer The print writer to dump the state to.
861         * @param args Optional dump arguments.
862         */
863        @Override
864        protected void dump(FileDescriptor fd, final PrintWriter writer, String[] args) {
865            if (mContext.checkCallingOrSelfPermission(
866                    android.Manifest.permission.DUMP)
867                    != PackageManager.PERMISSION_GRANTED) {
868                writer.println("Permission Denial: can't dump TelecomService " +
869                        "from from pid=" + Binder.getCallingPid() + ", uid=" +
870                        Binder.getCallingUid());
871                return;
872            }
873
874            final IndentingPrintWriter pw = new IndentingPrintWriter(writer, "  ");
875            if (mCallsManager != null) {
876                pw.println("CallsManager: ");
877                pw.increaseIndent();
878                mCallsManager.dump(pw);
879                pw.decreaseIndent();
880
881                pw.println("PhoneAccountRegistrar: ");
882                pw.increaseIndent();
883                mPhoneAccountRegistrar.dump(pw);
884                pw.decreaseIndent();
885            }
886
887            Log.dumpCallEvents(pw);
888        }
889    };
890
891    private Context mContext;
892    private AppOpsManager mAppOpsManager;
893    private UserManager mUserManager;
894    private PackageManager mPackageManager;
895    private CallsManager mCallsManager;
896    private final PhoneAccountRegistrar mPhoneAccountRegistrar;
897    private final TelecomSystem.SyncRoot mLock;
898
899    public TelecomServiceImpl(
900            Context context,
901            CallsManager callsManager,
902            PhoneAccountRegistrar phoneAccountRegistrar,
903            TelecomSystem.SyncRoot lock) {
904        mContext = context;
905        mAppOpsManager = (AppOpsManager) mContext.getSystemService(Context.APP_OPS_SERVICE);
906
907        mUserManager = (UserManager) mContext.getSystemService(Context.USER_SERVICE);
908        mPackageManager = mContext.getPackageManager();
909
910        mCallsManager = callsManager;
911        mLock = lock;
912        mPhoneAccountRegistrar = phoneAccountRegistrar;
913    }
914
915    public ITelecomService.Stub getBinder() {
916        return mBinderImpl;
917    }
918
919    //
920    // Supporting methods for the ITelecomService interface implementation.
921    //
922
923    private boolean isVisibleToCaller(PhoneAccountHandle accountHandle) {
924        if (accountHandle == null) {
925            return false;
926        }
927        return isVisibleToCaller(mPhoneAccountRegistrar.getPhoneAccount(accountHandle));
928    }
929
930    private boolean isVisibleToCaller(PhoneAccount account) {
931        if (account == null) {
932            return false;
933        }
934
935        // If this PhoneAccount has CAPABILITY_MULTI_USER, it should be visible to all users and
936        // all profiles. Only Telephony and SIP accounts should have this capability.
937        if (account.hasCapabilities(PhoneAccount.CAPABILITY_MULTI_USER)) {
938            return true;
939        }
940
941        UserHandle phoneAccountUserHandle = account.getAccountHandle().getUserHandle();
942        if (phoneAccountUserHandle == null) {
943            return false;
944        }
945
946        if (phoneAccountUserHandle.equals(Binder.getCallingUserHandle())) {
947            return true;
948        }
949
950        List<UserHandle> profileUserHandles;
951        if (UserHandle.getCallingUserId() == UserHandle.USER_OWNER) {
952            profileUserHandles = mUserManager.getUserProfiles();
953        } else {
954            // Otherwise, it has to be owned by the current caller's profile.
955            profileUserHandles = new ArrayList<>(1);
956            profileUserHandles.add(Binder.getCallingUserHandle());
957        }
958
959        return profileUserHandles.contains(phoneAccountUserHandle);
960    }
961
962    /**
963     * Given a list of {@link PhoneAccountHandle}s, filter them to the ones that the calling
964     * user can see.
965     *
966     * @param phoneAccountHandles Unfiltered list of account handles.
967     *
968     * @return {@link PhoneAccountHandle}s visible to the calling user and its profiles.
969     */
970    private List<PhoneAccountHandle> filterForAccountsVisibleToCaller(
971            List<PhoneAccountHandle> phoneAccountHandles) {
972        List<PhoneAccountHandle> profilePhoneAccountHandles =
973                new ArrayList<>(phoneAccountHandles.size());
974        for (PhoneAccountHandle phoneAccountHandle : phoneAccountHandles) {
975            if (isVisibleToCaller(phoneAccountHandle)) {
976                profilePhoneAccountHandles.add(phoneAccountHandle);
977            }
978        }
979        return profilePhoneAccountHandles;
980    }
981
982    private boolean isCallerSystemApp() {
983        int uid = Binder.getCallingUid();
984        String[] packages = mPackageManager.getPackagesForUid(uid);
985        for (String packageName : packages) {
986            if (isPackageSystemApp(packageName)) {
987                return true;
988            }
989        }
990        return false;
991    }
992
993    private boolean isPackageSystemApp(String packageName) {
994        try {
995            ApplicationInfo applicationInfo = mPackageManager.getApplicationInfo(packageName,
996                    PackageManager.GET_META_DATA);
997            if ((applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0) {
998                return true;
999            }
1000        } catch (PackageManager.NameNotFoundException e) {
1001        }
1002        return false;
1003    }
1004
1005    private void acceptRingingCallInternal() {
1006        Call call = mCallsManager.getFirstCallWithState(CallState.RINGING);
1007        if (call != null) {
1008            call.answer(call.getVideoState());
1009        }
1010    }
1011
1012    private boolean endCallInternal() {
1013        // Always operate on the foreground call if one exists, otherwise get the first call in
1014        // priority order by call-state.
1015        Call call = mCallsManager.getForegroundCall();
1016        if (call == null) {
1017            call = mCallsManager.getFirstCallWithState(
1018                    CallState.ACTIVE,
1019                    CallState.DIALING,
1020                    CallState.RINGING,
1021                    CallState.ON_HOLD);
1022        }
1023
1024        if (call != null) {
1025            if (call.getState() == CallState.RINGING) {
1026                call.reject(false /* rejectWithMessage */, null);
1027            } else {
1028                call.disconnect();
1029            }
1030            return true;
1031        }
1032
1033        return false;
1034    }
1035
1036    private void enforcePhoneAccountModificationForPackage(String packageName) {
1037        // TODO: Use a new telecomm permission for this instead of reusing modify.
1038
1039        int result = mContext.checkCallingOrSelfPermission(MODIFY_PHONE_STATE);
1040
1041        // Callers with MODIFY_PHONE_STATE can use the PhoneAccount mechanism to implement
1042        // built-in behavior even when PhoneAccounts are not exposed as a third-part API. They
1043        // may also modify PhoneAccounts on behalf of any 'packageName'.
1044
1045        if (result != PackageManager.PERMISSION_GRANTED) {
1046            // Other callers are only allowed to modify PhoneAccounts if the relevant system
1047            // feature is enabled ...
1048            enforceConnectionServiceFeature();
1049            // ... and the PhoneAccounts they refer to are for their own package.
1050            enforceCallingPackage(packageName);
1051        }
1052    }
1053
1054    private void enforcePermissionOrPrivilegedDialer(String permission, String packageName) {
1055        if (!isPrivilegedDialerCalling(packageName)) {
1056            try {
1057                enforcePermission(permission);
1058            } catch (SecurityException e) {
1059                Log.e(this, e, "Caller must be the default or system dialer, or have the permission"
1060                        + " %s to perform this operation.", permission);
1061                throw e;
1062            }
1063        }
1064    }
1065
1066    private void enforceCallingPackage(String packageName) {
1067        mAppOpsManager.checkPackage(Binder.getCallingUid(), packageName);
1068    }
1069
1070    private void enforceConnectionServiceFeature() {
1071        enforceFeature(PackageManager.FEATURE_CONNECTION_SERVICE);
1072    }
1073
1074    private void enforceRegisterSimSubscriptionPermission() {
1075        enforcePermission(REGISTER_SIM_SUBSCRIPTION);
1076    }
1077
1078    private void enforceModifyPermission() {
1079        enforcePermission(MODIFY_PHONE_STATE);
1080    }
1081
1082    private void enforcePermission(String permission) {
1083        mContext.enforceCallingOrSelfPermission(permission, null);
1084    }
1085
1086    private void enforceRegisterMultiUser() {
1087        if (!isCallerSystemApp()) {
1088            throw new SecurityException("CAPABILITY_MULTI_USER is only available to system apps.");
1089        }
1090    }
1091
1092    private void enforceUserHandleMatchesCaller(PhoneAccountHandle accountHandle) {
1093        if (!Binder.getCallingUserHandle().equals(accountHandle.getUserHandle())) {
1094            throw new SecurityException("Calling UserHandle does not match PhoneAccountHandle's");
1095        }
1096    }
1097
1098    private void enforceFeature(String feature) {
1099        PackageManager pm = mContext.getPackageManager();
1100        if (!pm.hasSystemFeature(feature)) {
1101            throw new UnsupportedOperationException(
1102                    "System does not support feature " + feature);
1103        }
1104    }
1105
1106    private boolean canReadPhoneState(String callingPackage, String message) {
1107        // The system/default dialer can always read phone state - so that emergency calls will
1108        // still work.
1109        if (isPrivilegedDialerCalling(callingPackage)) {
1110            return true;
1111        }
1112
1113        // Accessing phone state is gated by a special permission.
1114        mContext.enforceCallingOrSelfPermission(READ_PHONE_STATE, message);
1115
1116        // Some apps that have the permission can be restricted via app ops.
1117        return mAppOpsManager.noteOp(AppOpsManager.OP_READ_PHONE_STATE,
1118                Binder.getCallingUid(), callingPackage) == AppOpsManager.MODE_ALLOWED;
1119    }
1120
1121    private boolean canCallPhone(String callingPackage, String message) {
1122        // The system/default dialer can always read phone state - so that emergency calls will
1123        // still work.
1124        if (isPrivilegedDialerCalling(callingPackage)) {
1125            return true;
1126        }
1127
1128        // Accessing phone state is gated by a special permission.
1129        mContext.enforceCallingOrSelfPermission(CALL_PHONE, message);
1130
1131        // Some apps that have the permission can be restricted via app ops.
1132        return mAppOpsManager.noteOp(AppOpsManager.OP_CALL_PHONE,
1133                Binder.getCallingUid(), callingPackage) == AppOpsManager.MODE_ALLOWED;
1134    }
1135
1136    private boolean isCallerSimCallManager() {
1137        PhoneAccountHandle accountHandle = TelecomSystem.getInstance().getPhoneAccountRegistrar()
1138                .getSimCallManager();
1139        if (accountHandle != null) {
1140            try {
1141                mAppOpsManager.checkPackage(
1142                        Binder.getCallingUid(), accountHandle.getComponentName().getPackageName());
1143                return true;
1144            } catch (SecurityException e) {
1145            }
1146        }
1147        return false;
1148    }
1149
1150    private boolean isPrivilegedDialerCalling(String callingPackage) {
1151        mAppOpsManager.checkPackage(Binder.getCallingUid(), callingPackage);
1152        return DefaultDialerManager.isDefaultOrSystemDialer(mContext, callingPackage);
1153    }
1154
1155    private TelephonyManager getTelephonyManager() {
1156        return (TelephonyManager)mContext.getSystemService(Context.TELEPHONY_SERVICE);
1157    }
1158}
1159