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