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