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