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