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