TelecomServiceImpl.java revision a83f8a7012309177c75879c731132df0c8fc66f2
1/*
2 * Copyright (C) 2014 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package com.android.server.telecom;
18
19import static android.Manifest.permission.CALL_PHONE;
20import static android.Manifest.permission.MODIFY_PHONE_STATE;
21import static android.Manifest.permission.READ_PHONE_STATE;
22import static android.Manifest.permission.REGISTER_CALL_PROVIDER;
23import static android.Manifest.permission.REGISTER_CONNECTION_MANAGER;
24import static android.Manifest.permission.REGISTER_SIM_SUBSCRIPTION;
25import static android.Manifest.permission.WRITE_SECURE_SETTINGS;
26
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.w(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 : profilePhoneAccounts) {
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            synchronized (mLock) {
260                try {
261                    PhoneAccountHandle accountHandle = mPhoneAccountRegistrar.getSimCallManager();
262                    if (!isVisibleToCaller(accountHandle)) {
263                        Log.w(this, "%s is not visible for the calling user [gsCM]", accountHandle);
264                        return null;
265                    }
266                    return accountHandle;
267                } catch (Exception e) {
268                    Log.e(this, e, "getSimCallManager");
269                    throw e;
270                }
271            }
272        }
273
274        @Override
275        public void setSimCallManager(PhoneAccountHandle accountHandle) {
276            synchronized (mLock) {
277                enforceModifyPermission();
278                try {
279                    mPhoneAccountRegistrar.setSimCallManager(accountHandle);
280                } catch (Exception e) {
281                    Log.e(this, e, "setSimCallManager");
282                    throw e;
283                }
284            }
285        }
286
287        @Override
288        public List<PhoneAccountHandle> getSimCallManagers(String callingPackage) {
289            synchronized (mLock) {
290                if (!canReadPhoneState(callingPackage, "getSimCallManagers")) {
291                    return Collections.emptyList();
292                }
293
294                long token = Binder.clearCallingIdentity();
295                try {
296                    // TODO: Does this isVisible check actually work considering we are clearing
297                    // the calling identity?
298                    return filterForAccountsVisibleToCaller(
299                            mPhoneAccountRegistrar.getConnectionManagerPhoneAccounts());
300                } catch (Exception e) {
301                    Log.e(this, e, "getSimCallManagers");
302                    throw e;
303                } finally {
304                    Binder.restoreCallingIdentity(token);
305                }
306            }
307        }
308
309        @Override
310        public void registerPhoneAccount(PhoneAccount account) {
311            synchronized (mLock) {
312                try {
313                    enforcePhoneAccountModificationForPackage(
314                            account.getAccountHandle().getComponentName().getPackageName());
315                    if (account.hasCapabilities(PhoneAccount.CAPABILITY_CALL_PROVIDER)) {
316                        enforceRegisterCallProviderPermission();
317                    }
318                    if (account.hasCapabilities(PhoneAccount.CAPABILITY_SIM_SUBSCRIPTION)) {
319                        enforceRegisterSimSubscriptionPermission();
320                    }
321                    if (account.hasCapabilities(PhoneAccount.CAPABILITY_CONNECTION_MANAGER)) {
322                        enforceRegisterConnectionManagerPermission();
323                    }
324                    if (account.hasCapabilities(PhoneAccount.CAPABILITY_MULTI_USER)) {
325                        enforceRegisterMultiUser();
326                    }
327                    enforceUserHandleMatchesCaller(account.getAccountHandle());
328
329                    mPhoneAccountRegistrar.registerPhoneAccount(account);
330
331                    // Broadcast an intent indicating the phone account which was registered.
332                    long token = Binder.clearCallingIdentity();
333                    try {
334                        Intent intent = new Intent(TelecomManager.ACTION_PHONE_ACCOUNT_REGISTERED);
335                        intent.putExtra(TelecomManager.EXTRA_PHONE_ACCOUNT_HANDLE,
336                                account.getAccountHandle());
337                        Log.i(this, "Sending phone-account intent as user");
338                        mContext.sendBroadcastAsUser(intent, UserHandle.ALL,
339                                PERMISSION_PROCESS_PHONE_ACCOUNT_REGISTRATION);
340                    } finally {
341                        Binder.restoreCallingIdentity(token);
342                    }
343                } catch (Exception e) {
344                    Log.e(this, e, "registerPhoneAccount %s", account);
345                    throw e;
346                }
347            }
348        }
349
350        @Override
351        public void unregisterPhoneAccount(PhoneAccountHandle accountHandle) {
352            synchronized (mLock) {
353                try {
354                    enforcePhoneAccountModificationForPackage(
355                            accountHandle.getComponentName().getPackageName());
356                    enforceUserHandleMatchesCaller(accountHandle);
357                    mPhoneAccountRegistrar.unregisterPhoneAccount(accountHandle);
358                } catch (Exception e) {
359                    Log.e(this, e, "unregisterPhoneAccount %s", accountHandle);
360                    throw e;
361                }
362            }
363        }
364
365        @Override
366        public void clearAccounts(String packageName) {
367            synchronized (mLock) {
368                try {
369                    enforcePhoneAccountModificationForPackage(packageName);
370                    mPhoneAccountRegistrar
371                            .clearAccounts(packageName, Binder.getCallingUserHandle());
372                } catch (Exception e) {
373                    Log.e(this, e, "clearAccounts %s", packageName);
374                    throw e;
375                }
376            }
377        }
378
379        /**
380         * @see android.telecom.TelecomManager#isVoiceMailNumber
381         */
382        @Override
383        public boolean isVoiceMailNumber(PhoneAccountHandle accountHandle, String number,
384                String callingPackage) {
385            synchronized (mLock) {
386                if (!canReadPhoneState(callingPackage, "isVoiceMailNumber")) {
387                    return false;
388                }
389
390                if (!isVisibleToCaller(accountHandle)) {
391                    Log.w(this, "%s is not visible for the calling user [iVMN]", accountHandle);
392                    return false;
393                }
394
395                long token = Binder.clearCallingIdentity();
396                try {
397                    return mPhoneAccountRegistrar.isVoiceMailNumber(accountHandle, number);
398                } catch (Exception e) {
399                    Log.e(this, e, "getSubscriptionIdForPhoneAccount");
400                    throw e;
401                } finally {
402                    Binder.restoreCallingIdentity(token);
403                }
404            }
405        }
406
407        /**
408         * @see android.telecom.TelecomManager#getVoiceMailNumber
409         */
410        @Override
411        public String getVoiceMailNumber(PhoneAccountHandle accountHandle, String callingPackage) {
412            synchronized (mLock) {
413                if (!canReadPhoneState(callingPackage, "getVoiceMailNumber")) {
414                    return null;
415                }
416
417                try {
418                    if (!isVisibleToCaller(accountHandle)) {
419                        Log.w(this, "%s is not visible for the calling user [gVMN]", accountHandle);
420                        return null;
421                    }
422
423                    int subId = SubscriptionManager.getDefaultVoiceSubId();
424                    if (accountHandle != null) {
425                        subId = mPhoneAccountRegistrar
426                                .getSubscriptionIdForPhoneAccount(accountHandle);
427                    }
428                    return getTelephonyManager().getVoiceMailNumber(subId);
429                } catch (Exception e) {
430                    Log.e(this, e, "getSubscriptionIdForPhoneAccount");
431                    throw e;
432                }
433            }
434        }
435
436        /**
437         * @see android.telecom.TelecomManager#getLine1Number
438         */
439        @Override
440        public String getLine1Number(PhoneAccountHandle accountHandle, String callingPackage) {
441            if (!canReadPhoneState(callingPackage, "getLine1Number")) {
442                return null;
443            }
444
445            synchronized (mLock) {
446                if (!isVisibleToCaller(accountHandle)) {
447                    Log.w(this, "%s is not visible for the calling user [gL1N]", accountHandle);
448                    return null;
449                }
450
451                long token = Binder.clearCallingIdentity();
452                try {
453                    int subId =
454                            mPhoneAccountRegistrar.getSubscriptionIdForPhoneAccount(accountHandle);
455                    return getTelephonyManager().getLine1NumberForSubscriber(subId);
456                } catch (Exception e) {
457                    Log.e(this, e, "getSubscriptionIdForPhoneAccount");
458                    throw e;
459                } finally {
460                    Binder.restoreCallingIdentity(token);
461                }
462            }
463        }
464
465        /**
466         * @see android.telecom.TelecomManager#silenceRinger
467         */
468        @Override
469        public void silenceRinger(String callingPackage) {
470            synchronized (mLock) {
471                enforcePermissionOrPrivilegedDialer(MODIFY_PHONE_STATE, callingPackage);
472
473                long token = Binder.clearCallingIdentity();
474                try {
475                    Log.i(this, "Silence Ringer requested by %s", callingPackage);
476                    mCallsManager.getRinger().silence();
477                } finally {
478                    Binder.restoreCallingIdentity(token);
479                }
480            }
481        }
482
483        /**
484         * @see android.telecom.TelecomManager#getDefaultPhoneApp
485         * @deprecated - Use {@link android.telecom.TelecomManager#getDefaultDialerPackage()}
486         *         instead.
487         */
488        @Override
489        public ComponentName getDefaultPhoneApp() {
490            // No need to synchronize
491            Resources resources = mContext.getResources();
492            return new ComponentName(
493                    resources.getString(R.string.ui_default_package),
494                    resources.getString(R.string.dialer_default_class));
495        }
496
497        /**
498         * @return the package name of the current user-selected default dialer. If no default
499         *         has been selected, the package name of the system dialer is returned. If
500         *         neither exists, then {@code null} is returned.
501         * @see android.telecom.TelecomManager#getDefaultDialerPackage
502         */
503        @Override
504        public String getDefaultDialerPackage() {
505            final long token = Binder.clearCallingIdentity();
506            try {
507                return DefaultDialerManager.getDefaultDialerApplication(mContext);
508            } finally {
509                Binder.restoreCallingIdentity(token);
510            }
511        }
512
513        /**
514         * @see android.telecom.TelecomManager#getSystemDialerPackage
515         */
516        @Override
517        public String getSystemDialerPackage() {
518            return mContext.getResources().getString(R.string.ui_default_package);
519        }
520
521        /**
522         * @see android.telecom.TelecomManager#isInCall
523         */
524        @Override
525        public boolean isInCall(String callingPackage) {
526            if (!canReadPhoneState(callingPackage, "isInCall")) {
527                return false;
528            }
529
530            synchronized (mLock) {
531                final int callState = mCallsManager.getCallState();
532                return callState == TelephonyManager.CALL_STATE_OFFHOOK
533                        || callState == TelephonyManager.CALL_STATE_RINGING;
534            }
535        }
536
537        /**
538         * @see android.telecom.TelecomManager#isRinging
539         */
540        @Override
541        public boolean isRinging(String callingPackage) {
542            if (!canReadPhoneState(callingPackage, "isRinging")) {
543                return false;
544            }
545
546            synchronized (mLock) {
547                return mCallsManager.getCallState() == TelephonyManager.CALL_STATE_RINGING;
548            }
549        }
550
551        /**
552         * @see TelecomManager#getCallState
553         */
554        @Override
555        public int getCallState() {
556            synchronized (mLock) {
557                return mCallsManager.getCallState();
558            }
559        }
560
561        /**
562         * @see android.telecom.TelecomManager#endCall
563         */
564        @Override
565        public boolean endCall() {
566            synchronized (mLock) {
567                enforceModifyPermission();
568
569                long token = Binder.clearCallingIdentity();
570                try {
571                    return endCallInternal();
572                } finally {
573                    Binder.restoreCallingIdentity(token);
574                }
575            }
576        }
577
578        /**
579         * @see android.telecom.TelecomManager#acceptRingingCall
580         */
581        @Override
582        public void acceptRingingCall() {
583            synchronized (mLock) {
584                enforceModifyPermission();
585
586                long token = Binder.clearCallingIdentity();
587                try {
588                    acceptRingingCallInternal();
589                } finally {
590                    Binder.restoreCallingIdentity(token);
591                }
592            }
593        }
594
595        /**
596         * @see android.telecom.TelecomManager#showInCallScreen
597         */
598        @Override
599        public void showInCallScreen(boolean showDialpad, String callingPackage) {
600            if (!canReadPhoneState(callingPackage, "showInCallScreen")) {
601                return;
602            }
603
604            synchronized (mLock) {
605
606                long token = Binder.clearCallingIdentity();
607                try {
608                    mCallsManager.getInCallController().bringToForeground(showDialpad);
609                } finally {
610                    Binder.restoreCallingIdentity(token);
611                }
612            }
613        }
614
615        /**
616         * @see android.telecom.TelecomManager#cancelMissedCallsNotification
617         */
618        @Override
619        public void cancelMissedCallsNotification(String callingPackage) {
620            synchronized (mLock) {
621                enforcePermissionOrPrivilegedDialer(MODIFY_PHONE_STATE, callingPackage);
622                long token = Binder.clearCallingIdentity();
623                try {
624                    mCallsManager.getMissedCallNotifier().clearMissedCalls();
625                } finally {
626                    Binder.restoreCallingIdentity(token);
627                }
628            }
629        }
630
631        /**
632         * @see android.telecom.TelecomManager#handleMmi
633         */
634        @Override
635        public boolean handlePinMmi(String dialString, String callingPackage) {
636            synchronized (mLock) {
637                enforcePermissionOrPrivilegedDialer(MODIFY_PHONE_STATE, callingPackage);
638
639                // Switch identity so that TelephonyManager checks Telecom's permissions instead.
640                long token = Binder.clearCallingIdentity();
641                boolean retval = false;
642                try {
643                    retval = getTelephonyManager().handlePinMmi(dialString);
644                } finally {
645                    Binder.restoreCallingIdentity(token);
646                }
647
648                return retval;
649            }
650        }
651
652        /**
653         * @see android.telecom.TelecomManager#handleMmi
654         */
655        @Override
656        public boolean handlePinMmiForPhoneAccount(
657                PhoneAccountHandle accountHandle,
658                String dialString,
659                String callingPackage) {
660            synchronized (mLock) {
661                enforcePermissionOrPrivilegedDialer(MODIFY_PHONE_STATE, callingPackage);
662
663                if (!isVisibleToCaller(accountHandle)) {
664                    Log.w(this, "%s is not visible for the calling user [hMMI]", accountHandle);
665                    return false;
666                }
667
668                // Switch identity so that TelephonyManager checks Telecom's permissions instead.
669                long token = Binder.clearCallingIdentity();
670                boolean retval = false;
671                try {
672                    int subId = mPhoneAccountRegistrar
673                            .getSubscriptionIdForPhoneAccount(accountHandle);
674                    retval = getTelephonyManager().handlePinMmiForSubscriber(subId, dialString);
675                } finally {
676                    Binder.restoreCallingIdentity(token);
677                }
678
679                return retval;
680            }
681        }
682
683        /**
684         * @see android.telecom.TelecomManager#getAdnUriForPhoneAccount
685         */
686        @Override
687        public Uri getAdnUriForPhoneAccount(PhoneAccountHandle accountHandle,
688                String callingPackage) {
689            synchronized (mLock) {
690                enforcePermissionOrPrivilegedDialer(MODIFY_PHONE_STATE, callingPackage);
691
692                if (!isVisibleToCaller(accountHandle)) {
693                    Log.w(this, "%s is not visible for the calling user [gA4PA]", accountHandle);
694                    return null;
695                }
696
697                // Switch identity so that TelephonyManager checks Telecom's permissions instead.
698                long token = Binder.clearCallingIdentity();
699                String retval = "content://icc/adn/";
700                try {
701                    long subId = mPhoneAccountRegistrar
702                            .getSubscriptionIdForPhoneAccount(accountHandle);
703                    retval = retval + "subId/" + subId;
704                } finally {
705                    Binder.restoreCallingIdentity(token);
706                }
707
708                return Uri.parse(retval);
709            }
710        }
711
712        /**
713         * @see android.telecom.TelecomManager#isTtySupported
714         */
715        @Override
716        public boolean isTtySupported(String callingPackage) {
717            if (!canReadPhoneState(callingPackage, "hasVoiceMailNumber")) {
718                return false;
719            }
720
721            synchronized (mLock) {
722                return mCallsManager.isTtySupported();
723            }
724        }
725
726        /**
727         * @see android.telecom.TelecomManager#getCurrentTtyMode
728         */
729        @Override
730        public int getCurrentTtyMode(String callingPackage) {
731            if (!canReadPhoneState(callingPackage, "getCurrentTtyMode")) {
732                return TelecomManager.TTY_MODE_OFF;
733            }
734
735            synchronized (mLock) {
736                return mCallsManager.getCurrentTtyMode();
737            }
738        }
739
740        /**
741         * @see android.telecom.TelecomManager#addNewIncomingCall
742         */
743        @Override
744        public void addNewIncomingCall(PhoneAccountHandle phoneAccountHandle, Bundle extras) {
745            synchronized (mLock) {
746                Log.i(this, "Adding new incoming call with phoneAccountHandle %s",
747                        phoneAccountHandle);
748                if (phoneAccountHandle != null && phoneAccountHandle.getComponentName() != null) {
749                    mAppOpsManager.checkPackage(
750                            Binder.getCallingUid(),
751                            phoneAccountHandle.getComponentName().getPackageName());
752
753                    // Make sure it doesn't cross the UserHandle boundary
754                    enforceUserHandleMatchesCaller(phoneAccountHandle);
755                    long token = Binder.clearCallingIdentity();
756
757                    try {
758                        Intent intent = new Intent(TelecomManager.ACTION_INCOMING_CALL);
759                        intent.putExtra(TelecomManager.EXTRA_PHONE_ACCOUNT_HANDLE,
760                            phoneAccountHandle);
761                        intent.putExtra(CallIntentProcessor.KEY_IS_INCOMING_CALL, true);
762                        if (extras != null) {
763                            intent.putExtra(TelecomManager.EXTRA_INCOMING_CALL_EXTRAS, extras);
764                        }
765                        CallIntentProcessor.processIncomingCallIntent(mCallsManager, intent);
766                    } finally {
767                        Binder.restoreCallingIdentity(token);
768                    }
769                } else {
770                    Log.w(this,
771                            "Null phoneAccountHandle. Ignoring request to add new incoming call");
772                }
773            }
774        }
775
776        /**
777         * @see android.telecom.TelecomManager#addNewUnknownCall
778         */
779        @Override
780        public void addNewUnknownCall(PhoneAccountHandle phoneAccountHandle, Bundle extras) {
781            synchronized (mLock) {
782                if (phoneAccountHandle != null && phoneAccountHandle.getComponentName() != null) {
783                    mAppOpsManager.checkPackage(
784                            Binder.getCallingUid(),
785                            phoneAccountHandle.getComponentName().getPackageName());
786
787                    // Make sure it doesn't cross the UserHandle boundary
788                    enforceUserHandleMatchesCaller(phoneAccountHandle);
789                    long token = Binder.clearCallingIdentity();
790
791                    try {
792                        Intent intent = new Intent(TelecomManager.ACTION_NEW_UNKNOWN_CALL);
793                        intent.putExtras(extras);
794                        intent.putExtra(CallIntentProcessor.KEY_IS_UNKNOWN_CALL, true);
795                        intent.putExtra(TelecomManager.EXTRA_PHONE_ACCOUNT_HANDLE,
796                            phoneAccountHandle);
797                        CallIntentProcessor.processUnknownCallIntent(mCallsManager, intent);
798                    } finally {
799                        Binder.restoreCallingIdentity(token);
800                    }
801                } else {
802                    Log.i(this,
803                            "Null phoneAccountHandle or not initiated by Telephony. " +
804                            "Ignoring request to add new unknown call.");
805                }
806            }
807        }
808
809        /**
810         * @see android.telecom.TelecomManager#placeCall
811         */
812        @Override
813        public void placeCall(Uri handle, Bundle extras, String callingPackage) {
814            enforceCallingPackage(callingPackage);
815            if (!canCallPhone(callingPackage, "placeCall")) {
816                throw new SecurityException("Package " + callingPackage
817                        + " is not allowed to place phone calls");
818            }
819
820            synchronized (mLock) {
821                final UserHandle userHandle = Binder.getCallingUserHandle();
822                long token = Binder.clearCallingIdentity();
823                try {
824                    final Intent intent = new Intent(Intent.ACTION_CALL, handle);
825                    intent.putExtras(extras);
826                    new UserCallIntentProcessor(mContext, userHandle).processIntent(intent,
827                            callingPackage);
828                } finally {
829                    Binder.restoreCallingIdentity(token);
830                }
831            }
832        }
833
834        /**
835         * @see android.telecom.TelecomManager#enablePhoneAccount
836         */
837        @Override
838        public boolean enablePhoneAccount(PhoneAccountHandle accountHandle, boolean isEnabled) {
839            enforceModifyPermission();
840            synchronized (mLock) {
841                long token  = Binder.clearCallingIdentity();
842                try {
843                    // enable/disable phone account
844                    return mPhoneAccountRegistrar.enablePhoneAccount(accountHandle, isEnabled);
845                } finally {
846                    Binder.restoreCallingIdentity(token);
847                }
848            }
849        }
850
851        @Override
852        public boolean setDefaultDialer(String packageName) {
853            enforcePermission(MODIFY_PHONE_STATE);
854            enforcePermission(WRITE_SECURE_SETTINGS);
855            synchronized (mLock) {
856                long token  = Binder.clearCallingIdentity();
857                try {
858                    return DefaultDialerManager.setDefaultDialerApplication(mContext, packageName);
859                } finally {
860                    Binder.restoreCallingIdentity(token);
861                }
862            }
863        }
864
865        /**
866         * Dumps the current state of the TelecomService.  Used when generating problem reports.
867         *
868         * @param fd The file descriptor.
869         * @param writer The print writer to dump the state to.
870         * @param args Optional dump arguments.
871         */
872        @Override
873        protected void dump(FileDescriptor fd, final PrintWriter writer, String[] args) {
874            if (mContext.checkCallingOrSelfPermission(
875                    android.Manifest.permission.DUMP)
876                    != PackageManager.PERMISSION_GRANTED) {
877                writer.println("Permission Denial: can't dump TelecomService " +
878                        "from from pid=" + Binder.getCallingPid() + ", uid=" +
879                        Binder.getCallingUid());
880                return;
881            }
882
883            final IndentingPrintWriter pw = new IndentingPrintWriter(writer, "  ");
884            if (mCallsManager != null) {
885                pw.println("CallsManager: ");
886                pw.increaseIndent();
887                mCallsManager.dump(pw);
888                pw.decreaseIndent();
889
890                pw.println("PhoneAccountRegistrar: ");
891                pw.increaseIndent();
892                mPhoneAccountRegistrar.dump(pw);
893                pw.decreaseIndent();
894            }
895
896            Log.dumpCallEvents(pw);
897        }
898    };
899
900    private Context mContext;
901    private AppOpsManager mAppOpsManager;
902    private UserManager mUserManager;
903    private PackageManager mPackageManager;
904    private CallsManager mCallsManager;
905    private final PhoneAccountRegistrar mPhoneAccountRegistrar;
906    private final TelecomSystem.SyncRoot mLock;
907
908    public TelecomServiceImpl(
909            Context context,
910            CallsManager callsManager,
911            PhoneAccountRegistrar phoneAccountRegistrar,
912            TelecomSystem.SyncRoot lock) {
913        mContext = context;
914        mAppOpsManager = (AppOpsManager) mContext.getSystemService(Context.APP_OPS_SERVICE);
915
916        mUserManager = (UserManager) mContext.getSystemService(Context.USER_SERVICE);
917        mPackageManager = mContext.getPackageManager();
918
919        mCallsManager = callsManager;
920        mLock = lock;
921        mPhoneAccountRegistrar = phoneAccountRegistrar;
922    }
923
924    public ITelecomService.Stub getBinder() {
925        return mBinderImpl;
926    }
927
928    //
929    // Supporting methods for the ITelecomService interface implementation.
930    //
931
932    private boolean isVisibleToCaller(PhoneAccountHandle accountHandle) {
933        if (accountHandle == null) {
934            return false;
935        }
936        return isVisibleToCaller(mPhoneAccountRegistrar.getPhoneAccount(accountHandle));
937    }
938
939    private boolean isVisibleToCaller(PhoneAccount account) {
940        if (account == null) {
941            return false;
942        }
943
944        // If this PhoneAccount has CAPABILITY_MULTI_USER, it should be visible to all users and
945        // all profiles. Only Telephony and SIP accounts should have this capability.
946        if (account.hasCapabilities(PhoneAccount.CAPABILITY_MULTI_USER)) {
947            return true;
948        }
949
950        UserHandle phoneAccountUserHandle = account.getAccountHandle().getUserHandle();
951        if (phoneAccountUserHandle == null) {
952            return false;
953        }
954
955        if (phoneAccountUserHandle.equals(Binder.getCallingUserHandle())) {
956            return true;
957        }
958
959        List<UserHandle> profileUserHandles;
960        if (UserHandle.getCallingUserId() == UserHandle.USER_OWNER) {
961            profileUserHandles = mUserManager.getUserProfiles();
962        } else {
963            // Otherwise, it has to be owned by the current caller's profile.
964            profileUserHandles = new ArrayList<>(1);
965            profileUserHandles.add(Binder.getCallingUserHandle());
966        }
967
968        return profileUserHandles.contains(phoneAccountUserHandle);
969    }
970
971    /**
972     * Given a list of {@link PhoneAccountHandle}s, filter them to the ones that the calling
973     * user can see.
974     *
975     * @param phoneAccountHandles Unfiltered list of account handles.
976     *
977     * @return {@link PhoneAccountHandle}s visible to the calling user and its profiles.
978     */
979    private List<PhoneAccountHandle> filterForAccountsVisibleToCaller(
980            List<PhoneAccountHandle> phoneAccountHandles) {
981        List<PhoneAccountHandle> profilePhoneAccountHandles =
982                new ArrayList<>(phoneAccountHandles.size());
983        for (PhoneAccountHandle phoneAccountHandle : phoneAccountHandles) {
984            if (isVisibleToCaller(phoneAccountHandle)) {
985                profilePhoneAccountHandles.add(phoneAccountHandle);
986            }
987        }
988        return profilePhoneAccountHandles;
989    }
990
991    private boolean isCallerSystemApp() {
992        int uid = Binder.getCallingUid();
993        String[] packages = mPackageManager.getPackagesForUid(uid);
994        for (String packageName : packages) {
995            if (isPackageSystemApp(packageName)) {
996                return true;
997            }
998        }
999        return false;
1000    }
1001
1002    private boolean isPackageSystemApp(String packageName) {
1003        try {
1004            ApplicationInfo applicationInfo = mPackageManager.getApplicationInfo(packageName,
1005                    PackageManager.GET_META_DATA);
1006            if ((applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0) {
1007                return true;
1008            }
1009        } catch (PackageManager.NameNotFoundException e) {
1010        }
1011        return false;
1012    }
1013
1014    private void acceptRingingCallInternal() {
1015        Call call = mCallsManager.getFirstCallWithState(CallState.RINGING);
1016        if (call != null) {
1017            call.answer(call.getVideoState());
1018        }
1019    }
1020
1021    private boolean endCallInternal() {
1022        // Always operate on the foreground call if one exists, otherwise get the first call in
1023        // priority order by call-state.
1024        Call call = mCallsManager.getForegroundCall();
1025        if (call == null) {
1026            call = mCallsManager.getFirstCallWithState(
1027                    CallState.ACTIVE,
1028                    CallState.DIALING,
1029                    CallState.RINGING,
1030                    CallState.ON_HOLD);
1031        }
1032
1033        if (call != null) {
1034            if (call.getState() == CallState.RINGING) {
1035                call.reject(false /* rejectWithMessage */, null);
1036            } else {
1037                call.disconnect();
1038            }
1039            return true;
1040        }
1041
1042        return false;
1043    }
1044
1045    private void enforcePhoneAccountModificationForPackage(String packageName) {
1046        // TODO: Use a new telecomm permission for this instead of reusing modify.
1047
1048        int result = mContext.checkCallingOrSelfPermission(MODIFY_PHONE_STATE);
1049
1050        // Callers with MODIFY_PHONE_STATE can use the PhoneAccount mechanism to implement
1051        // built-in behavior even when PhoneAccounts are not exposed as a third-part API. They
1052        // may also modify PhoneAccounts on behalf of any 'packageName'.
1053
1054        if (result != PackageManager.PERMISSION_GRANTED) {
1055            // Other callers are only allowed to modify PhoneAccounts if the relevant system
1056            // feature is enabled ...
1057            enforceConnectionServiceFeature();
1058            // ... and the PhoneAccounts they refer to are for their own package.
1059            enforceCallingPackage(packageName);
1060        }
1061    }
1062
1063    private void enforcePermissionOrPrivilegedDialer(String permission, String packageName) {
1064        if (!isPrivilegedDialerCalling(packageName)) {
1065            try {
1066                enforcePermission(permission);
1067            } catch (SecurityException e) {
1068                Log.e(this, e, "Caller must be the default or system dialer, or have the permission"
1069                        + " %s to perform this operation.", permission);
1070                throw e;
1071            }
1072        }
1073    }
1074
1075    private void enforceCallingPackage(String packageName) {
1076        mAppOpsManager.checkPackage(Binder.getCallingUid(), packageName);
1077    }
1078
1079    private void enforceConnectionServiceFeature() {
1080        enforceFeature(PackageManager.FEATURE_CONNECTION_SERVICE);
1081    }
1082
1083    private void enforceRegisterCallProviderPermission() {
1084        enforcePermission(REGISTER_CALL_PROVIDER);
1085    }
1086
1087    private void enforceRegisterSimSubscriptionPermission() {
1088        enforcePermission(REGISTER_SIM_SUBSCRIPTION);
1089    }
1090
1091    private void enforceRegisterConnectionManagerPermission() {
1092        enforcePermission(REGISTER_CONNECTION_MANAGER);
1093    }
1094
1095    private void enforceModifyPermission() {
1096        enforcePermission(MODIFY_PHONE_STATE);
1097    }
1098
1099    private void enforcePermission(String permission) {
1100        mContext.enforceCallingOrSelfPermission(permission, null);
1101    }
1102
1103    private void enforceRegisterMultiUser() {
1104        if (!isCallerSystemApp()) {
1105            throw new SecurityException("CAPABILITY_MULTI_USER is only available to system apps.");
1106        }
1107    }
1108
1109    private void enforceUserHandleMatchesCaller(PhoneAccountHandle accountHandle) {
1110        if (!Binder.getCallingUserHandle().equals(accountHandle.getUserHandle())) {
1111            throw new SecurityException("Calling UserHandle does not match PhoneAccountHandle's");
1112        }
1113    }
1114
1115    private void enforceFeature(String feature) {
1116        PackageManager pm = mContext.getPackageManager();
1117        if (!pm.hasSystemFeature(feature)) {
1118            throw new UnsupportedOperationException(
1119                    "System does not support feature " + feature);
1120        }
1121    }
1122
1123    private boolean canReadPhoneState(String callingPackage, String message) {
1124        // The system/default dialer can always read phone state - so that emergency calls will
1125        // still work.
1126        if (isPrivilegedDialerCalling(callingPackage)) {
1127            return true;
1128        }
1129
1130        // Accessing phone state is gated by a special permission.
1131        mContext.enforceCallingOrSelfPermission(READ_PHONE_STATE, message);
1132
1133        // Some apps that have the permission can be restricted via app ops.
1134        return mAppOpsManager.noteOp(AppOpsManager.OP_READ_PHONE_STATE,
1135                Binder.getCallingUid(), callingPackage) == AppOpsManager.MODE_ALLOWED;
1136    }
1137
1138    private boolean canCallPhone(String callingPackage, String message) {
1139        // The system/default dialer can always read phone state - so that emergency calls will
1140        // still work.
1141        if (isPrivilegedDialerCalling(callingPackage)) {
1142            return true;
1143        }
1144
1145        // Accessing phone state is gated by a special permission.
1146        mContext.enforceCallingOrSelfPermission(CALL_PHONE, message);
1147
1148        // Some apps that have the permission can be restricted via app ops.
1149        return mAppOpsManager.noteOp(AppOpsManager.OP_CALL_PHONE,
1150                Binder.getCallingUid(), callingPackage) == AppOpsManager.MODE_ALLOWED;
1151    }
1152
1153    private boolean isCallerSimCallManager() {
1154        PhoneAccountHandle accountHandle = TelecomSystem.getInstance().getPhoneAccountRegistrar()
1155                .getSimCallManager();
1156        if (accountHandle != null) {
1157            try {
1158                mAppOpsManager.checkPackage(
1159                        Binder.getCallingUid(), accountHandle.getComponentName().getPackageName());
1160                return true;
1161            } catch (SecurityException e) {
1162            }
1163        }
1164        return false;
1165    }
1166
1167    private boolean isPrivilegedDialerCalling(String callingPackage) {
1168        mAppOpsManager.checkPackage(Binder.getCallingUid(), callingPackage);
1169        return DefaultDialerManager.isDefaultOrSystemDialer(mContext, callingPackage);
1170    }
1171
1172    private TelephonyManager getTelephonyManager() {
1173        return (TelephonyManager)mContext.getSystemService(Context.TELEPHONY_SERVICE);
1174    }
1175}
1176