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