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