• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
17 package com.android.server;
18 
19 import static android.telephony.SubscriptionManager.INVALID_SIM_SLOT_INDEX;
20 
21 import android.Manifest;
22 import android.app.AppOpsManager;
23 import android.app.PendingIntent;
24 import android.content.ComponentName;
25 import android.content.ContentProvider;
26 import android.content.ContentValues;
27 import android.content.Context;
28 import android.content.Intent;
29 import android.content.ServiceConnection;
30 import android.content.pm.PackageManager;
31 import android.net.Uri;
32 import android.os.Binder;
33 import android.os.Bundle;
34 import android.os.Handler;
35 import android.os.IBinder;
36 import android.os.Message;
37 import android.os.RemoteException;
38 import android.os.SystemClock;
39 import android.os.UserHandle;
40 import android.service.carrier.CarrierMessagingService;
41 import android.telephony.SmsManager;
42 import android.telephony.SubscriptionInfo;
43 import android.telephony.SubscriptionManager;
44 import android.telephony.TelephonyManager;
45 import android.util.Slog;
46 
47 import com.android.internal.telephony.IMms;
48 import com.android.internal.telephony.TelephonyPermissions;
49 import com.android.internal.telephony.util.TelephonyUtils;
50 import com.android.server.uri.NeededUriGrants;
51 import com.android.server.uri.UriGrantsManagerInternal;
52 
53 import java.util.List;
54 
55 /**
56  * This class is a proxy for MmsService APIs. We need this because MmsService runs
57  * in phone process and may crash anytime. This manages a connection to the actual
58  * MmsService and bridges the public SMS/MMS APIs with MmsService implementation.
59  */
60 public class MmsServiceBroker extends SystemService {
61     private static final String TAG = "MmsServiceBroker";
62 
63     private static final ComponentName MMS_SERVICE_COMPONENT =
64             new ComponentName("com.android.mms.service", "com.android.mms.service.MmsService");
65 
66     private static final int MSG_TRY_CONNECTING = 1;
67 
68     private static final Uri FAKE_SMS_SENT_URI = Uri.parse("content://sms/sent/0");
69     private static final Uri FAKE_MMS_SENT_URI = Uri.parse("content://mms/sent/0");
70     private static final Uri FAKE_SMS_DRAFT_URI = Uri.parse("content://sms/draft/0");
71     private static final Uri FAKE_MMS_DRAFT_URI = Uri.parse("content://mms/draft/0");
72 
73     private static final long SERVICE_CONNECTION_WAIT_TIME_MS = 4 * 1000L; // 4 seconds
74     private static final long RETRY_DELAY_ON_DISCONNECTION_MS = 3 * 1000L; // 3 seconds
75 
76     private Context mContext;
77     // The actual MMS service instance to invoke
78     private volatile IMms mService;
79 
80     // Cached system service instances
81     private volatile AppOpsManager mAppOpsManager = null;
82     private volatile PackageManager mPackageManager = null;
83     private volatile TelephonyManager mTelephonyManager = null;
84 
85     private final Handler mConnectionHandler = new Handler() {
86         @Override
87         public void handleMessage(Message msg) {
88             switch (msg.what) {
89                 case MSG_TRY_CONNECTING:
90                     tryConnecting();
91                     break;
92                 default:
93                     Slog.e(TAG, "Unknown message");
94             }
95         }
96     };
97 
98     private ServiceConnection mConnection = new ServiceConnection() {
99         @Override
100         public void onServiceConnected(ComponentName name, IBinder service) {
101             Slog.i(TAG, "MmsService connected");
102             synchronized (MmsServiceBroker.this) {
103                 mService = IMms.Stub.asInterface(Binder.allowBlocking(service));
104                 MmsServiceBroker.this.notifyAll();
105             }
106         }
107 
108         @Override
109         public void onServiceDisconnected(ComponentName name) {
110             Slog.i(TAG, "MmsService unexpectedly disconnected");
111             synchronized (MmsServiceBroker.this) {
112                 mService = null;
113                 MmsServiceBroker.this.notifyAll();
114             }
115             // Retry connecting, but not too eager (with a delay)
116             // since it may come back by itself.
117             mConnectionHandler.sendMessageDelayed(
118                     mConnectionHandler.obtainMessage(MSG_TRY_CONNECTING),
119                     RETRY_DELAY_ON_DISCONNECTION_MS);
120         }
121     };
122 
123     // Instance of IMms for returning failure to service API caller,
124     // used when MmsService cannot be connected.
125     private final IMms mServiceStubForFailure = new IMms() {
126 
127         @Override
128         public IBinder asBinder() {
129             return null;
130         }
131 
132         @Override
133         public void sendMessage(int subId, int callingUser, String callingPkg,
134                 Uri contentUri, String locationUrl, Bundle configOverrides,
135                 PendingIntent sentIntent, long messageId,
136                 String attributionTag) throws RemoteException {
137             returnPendingIntentWithError(sentIntent);
138         }
139 
140         @Override
141         public void downloadMessage(int subId, int callingUser, String callingPkg,
142                 String locationUrl, Uri contentUri, Bundle configOverrides,
143                 PendingIntent downloadedIntent,
144                 long messageId, String attributionTag) throws RemoteException {
145             returnPendingIntentWithError(downloadedIntent);
146         }
147 
148         @Override
149         public Uri importTextMessage(String callingPkg, String address, int type, String text,
150                 long timestampMillis, boolean seen, boolean read) throws RemoteException {
151             return null;
152         }
153 
154         @Override
155         public Uri importMultimediaMessage(int callingUser, String callingPkg,
156                 Uri contentUri, String messageId, long timestampSecs,
157                 boolean seen, boolean read) throws RemoteException {
158             return null;
159         }
160 
161         @Override
162         public boolean deleteStoredMessage(String callingPkg, Uri messageUri)
163                 throws RemoteException {
164             return false;
165         }
166 
167         @Override
168         public boolean deleteStoredConversation(String callingPkg, long conversationId)
169                 throws RemoteException {
170             return false;
171         }
172 
173         @Override
174         public boolean updateStoredMessageStatus(String callingPkg, Uri messageUri,
175                 ContentValues statusValues) throws RemoteException {
176             return false;
177         }
178 
179         @Override
180         public boolean archiveStoredConversation(String callingPkg, long conversationId,
181                 boolean archived) throws RemoteException {
182             return false;
183         }
184 
185         @Override
186         public Uri addTextMessageDraft(String callingPkg, String address, String text)
187                 throws RemoteException {
188             return null;
189         }
190 
191         @Override
192         public Uri addMultimediaMessageDraft(int callingUser, String callingPkg,
193                 Uri contentUri) throws RemoteException {
194             return null;
195         }
196 
197         @Override
198         public void sendStoredMessage(int subId, String callingPkg, Uri messageUri,
199                 Bundle configOverrides, PendingIntent sentIntent) throws RemoteException {
200             returnPendingIntentWithError(sentIntent);
201         }
202 
203         @Override
204         public void setAutoPersisting(String callingPkg, boolean enabled) throws RemoteException {
205             // Do nothing
206         }
207 
208         @Override
209         public boolean getAutoPersisting() throws RemoteException {
210             return false;
211         }
212 
213         private void returnPendingIntentWithError(PendingIntent pendingIntent) {
214             try {
215                 pendingIntent.send(mContext, SmsManager.MMS_ERROR_UNSPECIFIED, null);
216             } catch (PendingIntent.CanceledException e) {
217                 Slog.e(TAG, "Failed to return pending intent result", e);
218             }
219         }
220     };
221 
MmsServiceBroker(Context context)222     public MmsServiceBroker(Context context) {
223         super(context);
224         mContext = context;
225         mService = null;
226     }
227 
228     @Override
onStart()229     public void onStart() {
230         publishBinderService("imms", new BinderService());
231     }
232 
systemRunning()233     public void systemRunning() {
234         Slog.i(TAG, "Delay connecting to MmsService until an API is called");
235     }
236 
tryConnecting()237     private void tryConnecting() {
238         Slog.i(TAG, "Connecting to MmsService");
239         synchronized (this) {
240             if (mService != null) {
241                 Slog.d(TAG, "Already connected");
242                 return;
243             }
244             final Intent intent = new Intent();
245             intent.setComponent(MMS_SERVICE_COMPONENT);
246             try {
247                 if (!mContext.bindService(intent, mConnection, Context.BIND_AUTO_CREATE)) {
248                     Slog.e(TAG, "Failed to bind to MmsService");
249                 }
250             } catch (SecurityException e) {
251                 Slog.e(TAG, "Forbidden to bind to MmsService", e);
252             }
253         }
254     }
255 
getOrConnectService()256     private IMms getOrConnectService() {
257         synchronized (this) {
258             if (mService != null) {
259                 return mService;
260             }
261             // Service is not connected. Try blocking connecting.
262             Slog.w(TAG, "MmsService not connected. Try connecting...");
263             mConnectionHandler.sendMessage(
264                     mConnectionHandler.obtainMessage(MSG_TRY_CONNECTING));
265             final long shouldEnd =
266                     SystemClock.elapsedRealtime() + SERVICE_CONNECTION_WAIT_TIME_MS;
267             long waitTime = SERVICE_CONNECTION_WAIT_TIME_MS;
268             while (waitTime > 0) {
269                 try {
270                     // TODO: consider using Java concurrent construct instead of raw object wait
271                     this.wait(waitTime);
272                 } catch (InterruptedException e) {
273                     Slog.w(TAG, "Connection wait interrupted", e);
274                 }
275                 if (mService != null) {
276                     // Success
277                     return mService;
278                 }
279                 // Calculate remaining waiting time to make sure we wait the full timeout period
280                 waitTime = shouldEnd - SystemClock.elapsedRealtime();
281             }
282             // Timed out. Something's really wrong.
283             Slog.e(TAG, "Can not connect to MmsService (timed out)");
284             return null;
285         }
286     }
287 
288     /**
289      * Make sure to return a non-empty service instance. Return the connected MmsService
290      * instance, if not connected, try connecting. If fail to connect, return a fake service
291      * instance which returns failure to service caller.
292      *
293      * @return a non-empty service instance, real or fake
294      */
getServiceGuarded()295     private IMms getServiceGuarded() {
296         final IMms service = getOrConnectService();
297         if (service != null) {
298             return service;
299         }
300         return mServiceStubForFailure;
301     }
302 
getAppOpsManager()303     private AppOpsManager getAppOpsManager() {
304         if (mAppOpsManager == null) {
305             mAppOpsManager = (AppOpsManager) mContext.getSystemService(Context.APP_OPS_SERVICE);
306         }
307         return mAppOpsManager;
308     }
309 
getPackageManager()310     private PackageManager getPackageManager() {
311         if (mPackageManager == null) {
312             mPackageManager = mContext.getPackageManager();
313         }
314         return mPackageManager;
315     }
316 
getTelephonyManager()317     private TelephonyManager getTelephonyManager() {
318         if (mTelephonyManager == null) {
319             mTelephonyManager = (TelephonyManager) mContext.getSystemService(
320                     Context.TELEPHONY_SERVICE);
321         }
322         return mTelephonyManager;
323     }
324 
getCallingPackageName()325     private String getCallingPackageName() {
326         final String[] packages = getPackageManager().getPackagesForUid(Binder.getCallingUid());
327         if (packages != null && packages.length > 0) {
328             return packages[0];
329         }
330         return "unknown";
331     }
332 
333     // Service API calls implementation, proxied to the real MmsService in "com.android.mms.service"
334     private final class BinderService extends IMms.Stub {
335         private static final String PHONE_PACKAGE_NAME = "com.android.phone";
336 
337         @Override
sendMessage(int subId, int callingUser, String callingPkg, Uri contentUri, String locationUrl, Bundle configOverrides, PendingIntent sentIntent, long messageId, String attributionTag)338         public void sendMessage(int subId, int callingUser, String callingPkg,
339                 Uri contentUri, String locationUrl, Bundle configOverrides,
340                 PendingIntent sentIntent, long messageId, String attributionTag)
341                 throws RemoteException {
342             Slog.d(TAG, "sendMessage() by " + callingPkg);
343             mContext.enforceCallingPermission(Manifest.permission.SEND_SMS, "Send MMS message");
344 
345             // Check if user is associated with the subscription
346             if (!TelephonyPermissions.checkSubscriptionAssociatedWithUser(mContext, subId,
347                     Binder.getCallingUserHandle())
348                     // For inactive sub, fall through to MMS service to have it recorded in metrics.
349                     && isActiveSubId(subId)) {
350                 // Try remind user to use another profile to send.
351                 TelephonyUtils.showSwitchToManagedProfileDialogIfAppropriate(mContext,
352                         subId, Binder.getCallingUid(), callingPkg);
353                 return;
354             }
355 
356             if (getAppOpsManager().noteOp(AppOpsManager.OP_SEND_SMS, Binder.getCallingUid(),
357                     callingPkg, attributionTag, null) != AppOpsManager.MODE_ALLOWED) {
358                 Slog.e(TAG, callingPkg + " is not allowed to call sendMessage()");
359                 return;
360             }
361             contentUri = adjustUriForUserAndGrantPermission(contentUri,
362                     CarrierMessagingService.SERVICE_INTERFACE,
363                     Intent.FLAG_GRANT_READ_URI_PERMISSION,
364                     subId);
365             getServiceGuarded().sendMessage(subId, getCallingUserId(), callingPkg, contentUri,
366                     locationUrl, configOverrides, sentIntent, messageId, attributionTag);
367         }
368 
369         @Override
downloadMessage(int subId, int callingUser, String callingPkg, String locationUrl, Uri contentUri, Bundle configOverrides, PendingIntent downloadedIntent, long messageId, String attributionTag)370         public void downloadMessage(int subId, int callingUser, String callingPkg,
371                 String locationUrl, Uri contentUri, Bundle configOverrides,
372                 PendingIntent downloadedIntent, long messageId, String attributionTag)
373                 throws RemoteException {
374             Slog.d(TAG, "downloadMessage() by " + callingPkg);
375             mContext.enforceCallingPermission(Manifest.permission.RECEIVE_MMS,
376                     "Download MMS message");
377             if (getAppOpsManager().noteOp(AppOpsManager.OP_RECEIVE_MMS, Binder.getCallingUid(),
378                     callingPkg, attributionTag, null) != AppOpsManager.MODE_ALLOWED) {
379                 Slog.e(TAG, callingPkg + " is not allowed to call downloadMessage()");
380                 return;
381             }
382             contentUri = adjustUriForUserAndGrantPermission(contentUri,
383                     CarrierMessagingService.SERVICE_INTERFACE,
384                     Intent.FLAG_GRANT_READ_URI_PERMISSION | Intent.FLAG_GRANT_WRITE_URI_PERMISSION,
385                     subId);
386 
387             getServiceGuarded().downloadMessage(subId, getCallingUserId(), callingPkg, locationUrl,
388                     contentUri, configOverrides, downloadedIntent, messageId, attributionTag);
389         }
390 
391         @Override
importTextMessage(String callingPkg, String address, int type, String text, long timestampMillis, boolean seen, boolean read)392         public Uri importTextMessage(String callingPkg, String address, int type, String text,
393                 long timestampMillis, boolean seen, boolean read) throws RemoteException {
394             if (getAppOpsManager().noteOp(AppOpsManager.OP_WRITE_SMS, Binder.getCallingUid(),
395                     callingPkg, null, null) != AppOpsManager.MODE_ALLOWED) {
396                 // Silently fail AppOps failure due to not being the default SMS app
397                 // while writing the TelephonyProvider
398                 return FAKE_SMS_SENT_URI;
399             }
400             return getServiceGuarded().importTextMessage(
401                     callingPkg, address, type, text, timestampMillis, seen, read);
402         }
403 
404         @Override
importMultimediaMessage(int callingUser, String callingPkg, Uri contentUri, String messageId, long timestampSecs, boolean seen, boolean read)405         public Uri importMultimediaMessage(int callingUser, String callingPkg,
406                 Uri contentUri, String messageId, long timestampSecs, boolean seen, boolean read)
407                 throws RemoteException {
408             if (getAppOpsManager().noteOp(AppOpsManager.OP_WRITE_SMS, Binder.getCallingUid(),
409                     callingPkg, null, null) != AppOpsManager.MODE_ALLOWED) {
410                 // Silently fail AppOps failure due to not being the default SMS app
411                 // while writing the TelephonyProvider
412                 return FAKE_MMS_SENT_URI;
413             }
414             return getServiceGuarded().importMultimediaMessage(getCallingUserId(), callingPkg,
415                     contentUri, messageId, timestampSecs, seen, read);
416         }
417 
418         @Override
deleteStoredMessage(String callingPkg, Uri messageUri)419         public boolean deleteStoredMessage(String callingPkg, Uri messageUri)
420                 throws RemoteException {
421             if (getAppOpsManager().noteOp(AppOpsManager.OP_WRITE_SMS, Binder.getCallingUid(),
422                     callingPkg, null, null) != AppOpsManager.MODE_ALLOWED) {
423                 return false;
424             }
425             return getServiceGuarded().deleteStoredMessage(callingPkg, messageUri);
426         }
427 
428         @Override
deleteStoredConversation(String callingPkg, long conversationId)429         public boolean deleteStoredConversation(String callingPkg, long conversationId)
430                 throws RemoteException {
431             if (getAppOpsManager().noteOp(AppOpsManager.OP_WRITE_SMS, Binder.getCallingUid(),
432                     callingPkg, null, null) != AppOpsManager.MODE_ALLOWED) {
433                 return false;
434             }
435             return getServiceGuarded().deleteStoredConversation(callingPkg, conversationId);
436         }
437 
438         @Override
updateStoredMessageStatus(String callingPkg, Uri messageUri, ContentValues statusValues)439         public boolean updateStoredMessageStatus(String callingPkg, Uri messageUri,
440                 ContentValues statusValues) throws RemoteException {
441             if (getAppOpsManager().noteOp(AppOpsManager.OP_WRITE_SMS, Binder.getCallingUid(),
442                     callingPkg, null, null) != AppOpsManager.MODE_ALLOWED) {
443                 return false;
444             }
445             return getServiceGuarded()
446                     .updateStoredMessageStatus(callingPkg, messageUri, statusValues);
447         }
448 
449         @Override
archiveStoredConversation(String callingPkg, long conversationId, boolean archived)450         public boolean archiveStoredConversation(String callingPkg, long conversationId,
451                 boolean archived) throws RemoteException {
452             if (getAppOpsManager().noteOp(AppOpsManager.OP_WRITE_SMS, Binder.getCallingUid(),
453                     callingPkg, null, null) != AppOpsManager.MODE_ALLOWED) {
454                 return false;
455             }
456             return getServiceGuarded()
457                     .archiveStoredConversation(callingPkg, conversationId, archived);
458         }
459 
460         @Override
addTextMessageDraft(String callingPkg, String address, String text)461         public Uri addTextMessageDraft(String callingPkg, String address, String text)
462                 throws RemoteException {
463             if (getAppOpsManager().noteOp(AppOpsManager.OP_WRITE_SMS, Binder.getCallingUid(),
464                     callingPkg, null, null) != AppOpsManager.MODE_ALLOWED) {
465                 // Silently fail AppOps failure due to not being the default SMS app
466                 // while writing the TelephonyProvider
467                 return FAKE_SMS_DRAFT_URI;
468             }
469             return getServiceGuarded().addTextMessageDraft(callingPkg, address, text);
470         }
471 
472         @Override
addMultimediaMessageDraft(int callingUser, String callingPkg, Uri contentUri)473         public Uri addMultimediaMessageDraft(int callingUser, String callingPkg,
474                 Uri contentUri) throws RemoteException {
475             if (getAppOpsManager().noteOp(AppOpsManager.OP_WRITE_SMS, Binder.getCallingUid(),
476                     callingPkg, null, null) != AppOpsManager.MODE_ALLOWED) {
477                 // Silently fail AppOps failure due to not being the default SMS app
478                 // while writing the TelephonyProvider
479                 return FAKE_MMS_DRAFT_URI;
480             }
481             return getServiceGuarded().addMultimediaMessageDraft(getCallingUserId(), callingPkg,
482                     contentUri);
483         }
484 
485         @Override
sendStoredMessage(int subId, String callingPkg, Uri messageUri, Bundle configOverrides, PendingIntent sentIntent)486         public void sendStoredMessage(int subId, String callingPkg, Uri messageUri,
487                 Bundle configOverrides, PendingIntent sentIntent) throws RemoteException {
488             if (getAppOpsManager().noteOp(AppOpsManager.OP_SEND_SMS, Binder.getCallingUid(),
489                     callingPkg, null, null) != AppOpsManager.MODE_ALLOWED) {
490                 return;
491             }
492             getServiceGuarded().sendStoredMessage(subId, callingPkg, messageUri, configOverrides,
493                     sentIntent);
494         }
495 
496         @Override
setAutoPersisting(String callingPkg, boolean enabled)497         public void setAutoPersisting(String callingPkg, boolean enabled) throws RemoteException {
498             if (getAppOpsManager().noteOp(AppOpsManager.OP_WRITE_SMS, Binder.getCallingUid(),
499                     callingPkg, null, null) != AppOpsManager.MODE_ALLOWED) {
500                 return;
501             }
502             getServiceGuarded().setAutoPersisting(callingPkg, enabled);
503         }
504 
505         @Override
getAutoPersisting()506         public boolean getAutoPersisting() throws RemoteException {
507             return getServiceGuarded().getAutoPersisting();
508         }
509 
510         /**
511          * Modifies the Uri to contain the caller's userId, if necessary.
512          * Grants the phone package on primary user permission to access the contentUri,
513          * even if the caller is not in the primary user.
514          *
515          * @param contentUri The Uri to adjust
516          * @param action     The intent action used to find the associated carrier app
517          * @param permission The permission to add
518          * @return The adjusted Uri containing the calling userId.
519          */
adjustUriForUserAndGrantPermission(Uri contentUri, String action, int permission, int subId)520         private Uri adjustUriForUserAndGrantPermission(Uri contentUri, String action,
521                 int permission, int subId) {
522             final Intent grantIntent = new Intent();
523             grantIntent.setData(contentUri);
524             grantIntent.setFlags(permission);
525 
526             final int callingUid = Binder.getCallingUid();
527             final int callingUserId = UserHandle.getCallingUserId();
528             if (callingUserId != UserHandle.USER_SYSTEM) {
529                 contentUri = ContentProvider.maybeAddUserId(contentUri, callingUserId);
530             }
531 
532             final long token = Binder.clearCallingIdentity();
533             try {
534                 final UriGrantsManagerInternal ugm = LocalServices
535                         .getService(UriGrantsManagerInternal.class);
536                 final NeededUriGrants needed = ugm.checkGrantUriPermissionFromIntent(
537                         grantIntent, callingUid, PHONE_PACKAGE_NAME, UserHandle.USER_SYSTEM);
538                 ugm.grantUriPermissionUncheckedFromIntent(needed, null);
539 
540                 // Grant permission for the carrier app.
541                 Intent intent = new Intent(action);
542                 TelephonyManager telephonyManager = (TelephonyManager)
543                         mContext.getSystemService(Context.TELEPHONY_SERVICE);
544                 List<String> carrierPackages = telephonyManager
545                         .getCarrierPackageNamesForIntentAndPhone(
546                                 intent, getPhoneIdFromSubId(subId));
547                 if (carrierPackages != null && carrierPackages.size() == 1) {
548                     final NeededUriGrants carrierNeeded = ugm.checkGrantUriPermissionFromIntent(
549                             grantIntent, callingUid, carrierPackages.get(0),
550                             UserHandle.USER_SYSTEM);
551                     ugm.grantUriPermissionUncheckedFromIntent(carrierNeeded, null);
552                 }
553             } finally {
554                 Binder.restoreCallingIdentity(token);
555             }
556             return contentUri;
557         }
558     }
559 
560     /** @return true if the subId is active. */
isActiveSubId(int subId)561     private boolean isActiveSubId(int subId) {
562         final long token = Binder.clearCallingIdentity();
563         try {
564             SubscriptionManager subManager = mContext.getSystemService(SubscriptionManager.class);
565             return subManager != null && subManager.isActiveSubscriptionId(subId);
566         } finally {
567             Binder.restoreCallingIdentity(token);
568         }
569     }
570 
getPhoneIdFromSubId(int subId)571     private int getPhoneIdFromSubId(int subId) {
572         SubscriptionManager subManager = (SubscriptionManager)
573                 mContext.getSystemService(Context.TELEPHONY_SUBSCRIPTION_SERVICE);
574         if (subManager == null) return INVALID_SIM_SLOT_INDEX;
575         SubscriptionInfo info = subManager.getActiveSubscriptionInfo(subId);
576         if (info == null) return INVALID_SIM_SLOT_INDEX;
577         return info.getSimSlotIndex();
578     }
579 
580     /**
581      * Retrieves the  calling user id.
582      * @return The id of the calling user.
583      */
getCallingUserId()584     private int getCallingUserId() {
585         return Binder.getCallingUserHandle().getIdentifier();
586     }
587 
588 }
589