TelecomServiceImpl.java revision 72930a80679d461ad694b6555b0749d5fc4e31a8
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                    Log.startSession("TSI.pC");
867                    final Intent intent = new Intent(Intent.ACTION_CALL, handle);
868                    intent.putExtras(extras);
869                    new UserCallIntentProcessor(mContext, userHandle).processIntent(intent,
870                            callingPackage, hasCallAppOp && hasCallPermission);
871                } finally {
872                    Log.endSession();
873                    Binder.restoreCallingIdentity(token);
874                }
875            }
876        }
877
878        /**
879         * @see android.telecom.TelecomManager#enablePhoneAccount
880         */
881        @Override
882        public boolean enablePhoneAccount(PhoneAccountHandle accountHandle, boolean isEnabled) {
883            enforceModifyPermission();
884            synchronized (mLock) {
885                long token  = Binder.clearCallingIdentity();
886                try {
887                    // enable/disable phone account
888                    return mPhoneAccountRegistrar.enablePhoneAccount(accountHandle, isEnabled);
889                } finally {
890                    Binder.restoreCallingIdentity(token);
891                }
892            }
893        }
894
895        @Override
896        public boolean setDefaultDialer(String packageName) {
897            enforcePermission(MODIFY_PHONE_STATE);
898            enforcePermission(WRITE_SECURE_SETTINGS);
899            synchronized (mLock) {
900                long token  = Binder.clearCallingIdentity();
901                try {
902                    final boolean result =
903                            DefaultDialerManager.setDefaultDialerApplication(mContext, packageName);
904                    if (result) {
905                        final Intent intent =
906                                new Intent(TelecomManager.ACTION_DEFAULT_DIALER_CHANGED);
907                        intent.putExtra(TelecomManager.EXTRA_CHANGE_DEFAULT_DIALER_PACKAGE_NAME,
908                                packageName);
909                        mContext.sendBroadcastAsUser(intent,
910                                new UserHandle(ActivityManager.getCurrentUser()));
911                    }
912                    return result;
913                } finally {
914                    Binder.restoreCallingIdentity(token);
915                }
916            }
917        }
918
919        /**
920         * Dumps the current state of the TelecomService.  Used when generating problem reports.
921         *
922         * @param fd The file descriptor.
923         * @param writer The print writer to dump the state to.
924         * @param args Optional dump arguments.
925         */
926        @Override
927        protected void dump(FileDescriptor fd, final PrintWriter writer, String[] args) {
928            if (mContext.checkCallingOrSelfPermission(
929                    android.Manifest.permission.DUMP)
930                    != PackageManager.PERMISSION_GRANTED) {
931                writer.println("Permission Denial: can't dump TelecomService " +
932                        "from from pid=" + Binder.getCallingPid() + ", uid=" +
933                        Binder.getCallingUid());
934                return;
935            }
936
937            final IndentingPrintWriter pw = new IndentingPrintWriter(writer, "  ");
938            if (mCallsManager != null) {
939                pw.println("CallsManager: ");
940                pw.increaseIndent();
941                mCallsManager.dump(pw);
942                pw.decreaseIndent();
943
944                pw.println("PhoneAccountRegistrar: ");
945                pw.increaseIndent();
946                mPhoneAccountRegistrar.dump(pw);
947                pw.decreaseIndent();
948            }
949
950            Log.dumpCallEvents(pw);
951        }
952    };
953
954    private Context mContext;
955    private AppOpsManager mAppOpsManager;
956    private UserManager mUserManager;
957    private PackageManager mPackageManager;
958    private CallsManager mCallsManager;
959    private final PhoneAccountRegistrar mPhoneAccountRegistrar;
960    private final TelecomSystem.SyncRoot mLock;
961
962    public TelecomServiceImpl(
963            Context context,
964            CallsManager callsManager,
965            PhoneAccountRegistrar phoneAccountRegistrar,
966            TelecomSystem.SyncRoot lock) {
967        mContext = context;
968        mAppOpsManager = (AppOpsManager) mContext.getSystemService(Context.APP_OPS_SERVICE);
969
970        mUserManager = (UserManager) mContext.getSystemService(Context.USER_SERVICE);
971        mPackageManager = mContext.getPackageManager();
972
973        mCallsManager = callsManager;
974        mLock = lock;
975        mPhoneAccountRegistrar = phoneAccountRegistrar;
976    }
977
978    public ITelecomService.Stub getBinder() {
979        return mBinderImpl;
980    }
981
982    //
983    // Supporting methods for the ITelecomService interface implementation.
984    //
985
986    private boolean isVisibleToCaller(PhoneAccountHandle accountHandle) {
987        if (accountHandle == null) {
988            return false;
989        }
990        return isVisibleToCaller(mPhoneAccountRegistrar.getPhoneAccount(accountHandle));
991    }
992
993    private boolean isVisibleToCaller(PhoneAccount account) {
994        if (account == null) {
995            return false;
996        }
997
998        // If this PhoneAccount has CAPABILITY_MULTI_USER, it should be visible to all users and
999        // all profiles. Only Telephony and SIP accounts should have this capability.
1000        if (account.hasCapabilities(PhoneAccount.CAPABILITY_MULTI_USER)) {
1001            return true;
1002        }
1003
1004        UserHandle phoneAccountUserHandle = account.getAccountHandle().getUserHandle();
1005        if (phoneAccountUserHandle == null) {
1006            return false;
1007        }
1008
1009        if (phoneAccountUserHandle.equals(Binder.getCallingUserHandle())) {
1010            return true;
1011        }
1012
1013        // Any user can have profiles now.  Also result from getUserProfiles() includes the calling
1014        // user itself.
1015        List<UserHandle> profileUserHandles = mUserManager.getUserProfiles();
1016
1017        return profileUserHandles.contains(phoneAccountUserHandle);
1018    }
1019
1020    /**
1021     * Given a list of {@link PhoneAccountHandle}s, filter them to the ones that the calling
1022     * user can see.
1023     *
1024     * @param phoneAccountHandles Unfiltered list of account handles.
1025     *
1026     * @return {@link PhoneAccountHandle}s visible to the calling user and its profiles.
1027     */
1028    private List<PhoneAccountHandle> filterForAccountsVisibleToCaller(
1029            List<PhoneAccountHandle> phoneAccountHandles) {
1030        List<PhoneAccountHandle> profilePhoneAccountHandles =
1031                new ArrayList<>(phoneAccountHandles.size());
1032        for (PhoneAccountHandle phoneAccountHandle : phoneAccountHandles) {
1033            if (isVisibleToCaller(phoneAccountHandle)) {
1034                profilePhoneAccountHandles.add(phoneAccountHandle);
1035            }
1036        }
1037        return profilePhoneAccountHandles;
1038    }
1039
1040    private boolean isCallerSystemApp() {
1041        int uid = Binder.getCallingUid();
1042        String[] packages = mPackageManager.getPackagesForUid(uid);
1043        for (String packageName : packages) {
1044            if (isPackageSystemApp(packageName)) {
1045                return true;
1046            }
1047        }
1048        return false;
1049    }
1050
1051    private boolean isPackageSystemApp(String packageName) {
1052        try {
1053            ApplicationInfo applicationInfo = mPackageManager.getApplicationInfo(packageName,
1054                    PackageManager.GET_META_DATA);
1055            if ((applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0) {
1056                return true;
1057            }
1058        } catch (PackageManager.NameNotFoundException e) {
1059        }
1060        return false;
1061    }
1062
1063    private void acceptRingingCallInternal(int videoState) {
1064        Call call = mCallsManager.getFirstCallWithState(CallState.RINGING);
1065        if (call != null) {
1066            if (videoState == DEFAULT_VIDEO_STATE || !isValidAcceptVideoState(videoState)) {
1067                videoState = call.getVideoState();
1068            }
1069            call.answer(videoState);
1070        }
1071    }
1072
1073    private boolean endCallInternal() {
1074        // Always operate on the foreground call if one exists, otherwise get the first call in
1075        // priority order by call-state.
1076        Call call = mCallsManager.getForegroundCall();
1077        if (call == null) {
1078            call = mCallsManager.getFirstCallWithState(
1079                    CallState.ACTIVE,
1080                    CallState.DIALING,
1081                    CallState.RINGING,
1082                    CallState.ON_HOLD);
1083        }
1084
1085        if (call != null) {
1086            if (call.getState() == CallState.RINGING) {
1087                call.reject(false /* rejectWithMessage */, null);
1088            } else {
1089                call.disconnect();
1090            }
1091            return true;
1092        }
1093
1094        return false;
1095    }
1096
1097    private void enforcePhoneAccountModificationForPackage(String packageName) {
1098        // TODO: Use a new telecomm permission for this instead of reusing modify.
1099
1100        int result = mContext.checkCallingOrSelfPermission(MODIFY_PHONE_STATE);
1101
1102        // Callers with MODIFY_PHONE_STATE can use the PhoneAccount mechanism to implement
1103        // built-in behavior even when PhoneAccounts are not exposed as a third-part API. They
1104        // may also modify PhoneAccounts on behalf of any 'packageName'.
1105
1106        if (result != PackageManager.PERMISSION_GRANTED) {
1107            // Other callers are only allowed to modify PhoneAccounts if the relevant system
1108            // feature is enabled ...
1109            enforceConnectionServiceFeature();
1110            // ... and the PhoneAccounts they refer to are for their own package.
1111            enforceCallingPackage(packageName);
1112        }
1113    }
1114
1115    private void enforcePermissionOrPrivilegedDialer(String permission, String packageName) {
1116        if (!isPrivilegedDialerCalling(packageName)) {
1117            try {
1118                enforcePermission(permission);
1119            } catch (SecurityException e) {
1120                Log.e(this, e, "Caller must be the default or system dialer, or have the permission"
1121                        + " %s to perform this operation.", permission);
1122                throw e;
1123            }
1124        }
1125    }
1126
1127    private void enforceCallingPackage(String packageName) {
1128        mAppOpsManager.checkPackage(Binder.getCallingUid(), packageName);
1129    }
1130
1131    private void enforceConnectionServiceFeature() {
1132        enforceFeature(PackageManager.FEATURE_CONNECTION_SERVICE);
1133    }
1134
1135    private void enforceRegisterSimSubscriptionPermission() {
1136        enforcePermission(REGISTER_SIM_SUBSCRIPTION);
1137    }
1138
1139    private void enforceModifyPermission() {
1140        enforcePermission(MODIFY_PHONE_STATE);
1141    }
1142
1143    private void enforcePermission(String permission) {
1144        mContext.enforceCallingOrSelfPermission(permission, null);
1145    }
1146
1147    private void enforceRegisterMultiUser() {
1148        if (!isCallerSystemApp()) {
1149            throw new SecurityException("CAPABILITY_MULTI_USER is only available to system apps.");
1150        }
1151    }
1152
1153    private void enforceUserHandleMatchesCaller(PhoneAccountHandle accountHandle) {
1154        if (!Binder.getCallingUserHandle().equals(accountHandle.getUserHandle())) {
1155            throw new SecurityException("Calling UserHandle does not match PhoneAccountHandle's");
1156        }
1157    }
1158
1159    private void enforceFeature(String feature) {
1160        PackageManager pm = mContext.getPackageManager();
1161        if (!pm.hasSystemFeature(feature)) {
1162            throw new UnsupportedOperationException(
1163                    "System does not support feature " + feature);
1164        }
1165    }
1166
1167    private boolean canReadPhoneState(String callingPackage, String message) {
1168        // The system/default dialer can always read phone state - so that emergency calls will
1169        // still work.
1170        if (isPrivilegedDialerCalling(callingPackage)) {
1171            return true;
1172        }
1173
1174        try {
1175            mContext.enforceCallingOrSelfPermission(READ_PRIVILEGED_PHONE_STATE, message);
1176            // SKIP checking run-time OP_READ_PHONE_STATE since caller or self has PRIVILEGED
1177            // permission
1178            return true;
1179        } catch (SecurityException e) {
1180            // Accessing phone state is gated by a special permission.
1181            mContext.enforceCallingOrSelfPermission(READ_PHONE_STATE, message);
1182
1183            // Some apps that have the permission can be restricted via app ops.
1184            return mAppOpsManager.noteOp(AppOpsManager.OP_READ_PHONE_STATE,
1185                    Binder.getCallingUid(), callingPackage) == AppOpsManager.MODE_ALLOWED;
1186        }
1187    }
1188
1189    private boolean canCallPhone(String callingPackage, String message) {
1190        // The system/default dialer can always read phone state - so that emergency calls will
1191        // still work.
1192        if (isPrivilegedDialerCalling(callingPackage)) {
1193            return true;
1194        }
1195
1196        // Accessing phone state is gated by a special permission.
1197        mContext.enforceCallingOrSelfPermission(CALL_PHONE, message);
1198
1199        // Some apps that have the permission can be restricted via app ops.
1200        return mAppOpsManager.noteOp(AppOpsManager.OP_CALL_PHONE,
1201                Binder.getCallingUid(), callingPackage) == AppOpsManager.MODE_ALLOWED;
1202    }
1203
1204    private boolean isCallerSimCallManager() {
1205        PhoneAccountHandle accountHandle = null;
1206        long token = Binder.clearCallingIdentity();
1207        try {
1208            accountHandle = mPhoneAccountRegistrar.getSimCallManager();
1209        } finally {
1210            Binder.restoreCallingIdentity(token);
1211        }
1212
1213        if (accountHandle != null) {
1214            try {
1215                mAppOpsManager.checkPackage(
1216                        Binder.getCallingUid(), accountHandle.getComponentName().getPackageName());
1217                return true;
1218            } catch (SecurityException e) {
1219            }
1220        }
1221        return false;
1222    }
1223
1224    private boolean isPrivilegedDialerCalling(String callingPackage) {
1225        mAppOpsManager.checkPackage(Binder.getCallingUid(), callingPackage);
1226        return DefaultDialerManager.isDefaultOrSystemDialer(mContext, callingPackage);
1227    }
1228
1229    private TelephonyManager getTelephonyManager() {
1230        return (TelephonyManager)mContext.getSystemService(Context.TELEPHONY_SERVICE);
1231    }
1232
1233    /**
1234     * Determines if a video state is valid for accepting an incoming call.
1235     * For the purpose of accepting a call, states {@link VideoProfile#STATE_AUDIO_ONLY}, and
1236     * any combination of {@link VideoProfile#STATE_RX_ENABLED} and
1237     * {@link VideoProfile#STATE_TX_ENABLED} are considered valid.
1238     *
1239     * @param videoState The video state.
1240     * @return {@code true} if the video state is valid, {@code false} otherwise.
1241     */
1242    private boolean isValidAcceptVideoState(int videoState) {
1243        // Given a video state input, turn off TX and RX so that we can determine if those were the
1244        // only bits set.
1245        int remainingState = videoState & ~VideoProfile.STATE_TX_ENABLED;
1246        remainingState = remainingState & ~VideoProfile.STATE_RX_ENABLED;
1247
1248        // If only TX or RX were set (or neither), the video state is valid.
1249        return remainingState == 0;
1250    }
1251}
1252