• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2006 The Android Open Source Project
3  * Copyright (c) 2011-2013, The Linux Foundation. All rights reserved.
4  * Not a Contribution.
5  *
6  * Licensed under the Apache License, Version 2.0 (the "License");
7  * you may not use this file except in compliance with the License.
8  * You may obtain a copy of the License at
9  *
10  *      http://www.apache.org/licenses/LICENSE-2.0
11  *
12  * Unless required by applicable law or agreed to in writing, software
13  * distributed under the License is distributed on an "AS IS" BASIS,
14  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15  * See the License for the specific language governing permissions and
16  * limitations under the License.
17  */
18 
19 package com.android.internal.telephony;
20 
21 import static android.Manifest.permission.MODIFY_PHONE_STATE;
22 import static android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE;
23 
24 import android.annotation.NonNull;
25 import android.annotation.Nullable;
26 import android.compat.annotation.UnsupportedAppUsage;
27 import android.content.Context;
28 import android.content.pm.PackageManager;
29 import android.os.Binder;
30 import android.os.Build;
31 import android.os.RemoteException;
32 import android.os.TelephonyServiceManager.ServiceRegisterer;
33 import android.os.UserHandle;
34 import android.telephony.ImsiEncryptionInfo;
35 import android.telephony.PhoneNumberUtils;
36 import android.telephony.SubscriptionManager;
37 import android.telephony.TelephonyFrameworkInitializer;
38 
39 import com.android.internal.telephony.uicc.IsimRecords;
40 import com.android.internal.telephony.uicc.UiccCard;
41 import com.android.internal.telephony.uicc.UiccCardApplication;
42 import com.android.telephony.Rlog;
43 
44 public class PhoneSubInfoController extends IPhoneSubInfo.Stub {
45     private static final String TAG = "PhoneSubInfoController";
46     private static final boolean DBG = true;
47     private static final boolean VDBG = false; // STOPSHIP if true
48 
49     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
50     private final Context mContext;
51 
PhoneSubInfoController(Context context)52     public PhoneSubInfoController(Context context) {
53         ServiceRegisterer phoneSubServiceRegisterer = TelephonyFrameworkInitializer
54                 .getTelephonyServiceManager()
55                 .getPhoneSubServiceRegisterer();
56         if (phoneSubServiceRegisterer.get() == null) {
57             phoneSubServiceRegisterer.register(this);
58         }
59         mContext = context;
60     }
61 
62     @Deprecated
getDeviceId(String callingPackage)63     public String getDeviceId(String callingPackage) {
64         return getDeviceIdWithFeature(callingPackage, null);
65     }
66 
getDeviceIdWithFeature(String callingPackage, String callingFeatureId)67     public String getDeviceIdWithFeature(String callingPackage, String callingFeatureId) {
68         return getDeviceIdForPhone(SubscriptionManager.getPhoneId(getDefaultSubscription()),
69                 callingPackage, callingFeatureId);
70     }
71 
getDeviceIdForPhone(int phoneId, String callingPackage, String callingFeatureId)72     public String getDeviceIdForPhone(int phoneId, String callingPackage,
73             String callingFeatureId) {
74         return callPhoneMethodForPhoneIdWithReadDeviceIdentifiersCheck(phoneId, callingPackage,
75                 callingFeatureId, "getDeviceId", (phone) -> phone.getDeviceId());
76     }
77 
getNaiForSubscriber(int subId, String callingPackage, String callingFeatureId)78     public String getNaiForSubscriber(int subId, String callingPackage, String callingFeatureId) {
79         return callPhoneMethodForSubIdWithReadSubscriberIdentifiersCheck(subId, callingPackage,
80                 callingFeatureId, "getNai", (phone)-> phone.getNai());
81     }
82 
getImeiForSubscriber(int subId, String callingPackage, String callingFeatureId)83     public String getImeiForSubscriber(int subId, String callingPackage,
84             String callingFeatureId) {
85         return callPhoneMethodForSubIdWithReadDeviceIdentifiersCheck(subId, callingPackage,
86                 callingFeatureId, "getImei", (phone) -> phone.getImei());
87     }
88 
getCarrierInfoForImsiEncryption(int subId, int keyType, String callingPackage)89     public ImsiEncryptionInfo getCarrierInfoForImsiEncryption(int subId, int keyType,
90                                                               String callingPackage) {
91         return callPhoneMethodForSubIdWithPrivilegedCheck(subId,
92                 "getCarrierInfoForImsiEncryption",
93                 (phone)-> phone.getCarrierInfoForImsiEncryption(keyType, true));
94     }
95 
setCarrierInfoForImsiEncryption(int subId, String callingPackage, ImsiEncryptionInfo imsiEncryptionInfo)96     public void setCarrierInfoForImsiEncryption(int subId, String callingPackage,
97                                                 ImsiEncryptionInfo imsiEncryptionInfo) {
98         callPhoneMethodForSubIdWithModifyCheck(subId, callingPackage,
99                 "setCarrierInfoForImsiEncryption",
100                 (phone)-> {
101                     phone.setCarrierInfoForImsiEncryption(imsiEncryptionInfo);
102                     return null;
103                 });
104     }
105 
106     /**
107      *  Resets the Carrier Keys in the database. This involves 2 steps:
108      *  1. Delete the keys from the database.
109      *  2. Send an intent to download new Certificates.
110      *  @param subId
111      *  @param callingPackage
112      */
resetCarrierKeysForImsiEncryption(int subId, String callingPackage)113     public void resetCarrierKeysForImsiEncryption(int subId, String callingPackage) {
114         callPhoneMethodForSubIdWithModifyCheck(subId, callingPackage,
115                 "resetCarrierKeysForImsiEncryption",
116                 (phone)-> {
117                     phone.resetCarrierKeysForImsiEncryption();
118                     return null;
119                 });
120     }
121 
getDeviceSvn(String callingPackage, String callingFeatureId)122     public String getDeviceSvn(String callingPackage, String callingFeatureId) {
123         return getDeviceSvnUsingSubId(getDefaultSubscription(), callingPackage, callingFeatureId);
124     }
125 
getDeviceSvnUsingSubId(int subId, String callingPackage, String callingFeatureId)126     public String getDeviceSvnUsingSubId(int subId, String callingPackage,
127             String callingFeatureId) {
128         return callPhoneMethodForSubIdWithReadCheck(subId, callingPackage, callingFeatureId,
129                 "getDeviceSvn", (phone)-> phone.getDeviceSvn());
130     }
131 
132     @Deprecated
getSubscriberId(String callingPackage)133     public String getSubscriberId(String callingPackage) {
134         return getSubscriberIdWithFeature(callingPackage, null);
135     }
136 
getSubscriberIdWithFeature(String callingPackage, String callingFeatureId)137     public String getSubscriberIdWithFeature(String callingPackage, String callingFeatureId) {
138         return getSubscriberIdForSubscriber(getDefaultSubscription(), callingPackage,
139                 callingFeatureId);
140     }
141 
getSubscriberIdForSubscriber(int subId, String callingPackage, String callingFeatureId)142     public String getSubscriberIdForSubscriber(int subId, String callingPackage,
143             String callingFeatureId) {
144         String message = "getSubscriberIdForSubscriber";
145 
146         enforceCallingPackage(callingPackage, Binder.getCallingUid(), message);
147 
148         long identity = Binder.clearCallingIdentity();
149         boolean isActive;
150         try {
151             isActive = SubscriptionController.getInstance().isActiveSubId(subId, callingPackage,
152                     callingFeatureId);
153         } finally {
154             Binder.restoreCallingIdentity(identity);
155         }
156         if (isActive) {
157             return callPhoneMethodForSubIdWithReadSubscriberIdentifiersCheck(subId, callingPackage,
158                     callingFeatureId, message, (phone) -> phone.getSubscriberId());
159         } else {
160             if (!TelephonyPermissions.checkCallingOrSelfReadSubscriberIdentifiers(
161                     mContext, subId, callingPackage, callingFeatureId, message)) {
162                 return null;
163             }
164             identity = Binder.clearCallingIdentity();
165             try {
166                 return SubscriptionController.getInstance().getImsiPrivileged(subId);
167             } finally {
168                 Binder.restoreCallingIdentity(identity);
169             }
170         }
171     }
172 
173     @Deprecated
getIccSerialNumber(String callingPackage)174     public String getIccSerialNumber(String callingPackage) {
175         return getIccSerialNumberWithFeature(callingPackage, null);
176     }
177 
178     /**
179      * Retrieves the serial number of the ICC, if applicable.
180      */
getIccSerialNumberWithFeature(String callingPackage, String callingFeatureId)181     public String getIccSerialNumberWithFeature(String callingPackage, String callingFeatureId) {
182         return getIccSerialNumberForSubscriber(getDefaultSubscription(), callingPackage,
183                 callingFeatureId);
184     }
185 
getIccSerialNumberForSubscriber(int subId, String callingPackage, String callingFeatureId)186     public String getIccSerialNumberForSubscriber(int subId, String callingPackage,
187             String callingFeatureId) {
188         return callPhoneMethodForSubIdWithReadSubscriberIdentifiersCheck(subId, callingPackage,
189                 callingFeatureId, "getIccSerialNumber", (phone) -> phone.getIccSerialNumber());
190     }
191 
getLine1Number(String callingPackage, String callingFeatureId)192     public String getLine1Number(String callingPackage, String callingFeatureId) {
193         return getLine1NumberForSubscriber(getDefaultSubscription(), callingPackage,
194                 callingFeatureId);
195     }
196 
197     // In R and beyond, READ_PHONE_NUMBERS includes READ_PHONE_NUMBERS and READ_SMS only.
198     // Prior to R, it also included READ_PHONE_STATE.  Maintain that for compatibility.
getLine1NumberForSubscriber(int subId, String callingPackage, String callingFeatureId)199     public String getLine1NumberForSubscriber(int subId, String callingPackage,
200             String callingFeatureId) {
201         return callPhoneMethodForSubIdWithReadPhoneNumberCheck(
202                 subId, callingPackage, callingFeatureId, "getLine1Number",
203                 (phone)-> phone.getLine1Number());
204     }
205 
getLine1AlphaTag(String callingPackage, String callingFeatureId)206     public String getLine1AlphaTag(String callingPackage, String callingFeatureId) {
207         return getLine1AlphaTagForSubscriber(getDefaultSubscription(), callingPackage,
208                 callingFeatureId);
209     }
210 
getLine1AlphaTagForSubscriber(int subId, String callingPackage, String callingFeatureId)211     public String getLine1AlphaTagForSubscriber(int subId, String callingPackage,
212             String callingFeatureId) {
213         return callPhoneMethodForSubIdWithReadCheck(subId, callingPackage, callingFeatureId,
214                 "getLine1AlphaTag", (phone)-> phone.getLine1AlphaTag());
215     }
216 
getMsisdn(String callingPackage, String callingFeatureId)217     public String getMsisdn(String callingPackage, String callingFeatureId) {
218         return getMsisdnForSubscriber(getDefaultSubscription(), callingPackage, callingFeatureId);
219     }
220 
221     // In R and beyond this will require READ_PHONE_NUMBERS.
222     // Prior to R it needed READ_PHONE_STATE.  Maintain that for compatibility.
getMsisdnForSubscriber(int subId, String callingPackage, String callingFeatureId)223     public String getMsisdnForSubscriber(int subId, String callingPackage,
224             String callingFeatureId) {
225         return callPhoneMethodForSubIdWithReadPhoneNumberCheck(
226                 subId, callingPackage, callingFeatureId, "getMsisdn", (phone)-> phone.getMsisdn());
227     }
228 
getVoiceMailNumber(String callingPackage, String callingFeatureId)229     public String getVoiceMailNumber(String callingPackage, String callingFeatureId) {
230         return getVoiceMailNumberForSubscriber(getDefaultSubscription(), callingPackage,
231                 callingFeatureId);
232     }
233 
getVoiceMailNumberForSubscriber(int subId, String callingPackage, String callingFeatureId)234     public String getVoiceMailNumberForSubscriber(int subId, String callingPackage,
235             String callingFeatureId) {
236         return callPhoneMethodForSubIdWithReadCheck(subId, callingPackage, callingFeatureId,
237                 "getVoiceMailNumber", (phone)-> {
238                     String number = PhoneNumberUtils.extractNetworkPortion(
239                             phone.getVoiceMailNumber());
240                     if (VDBG) log("VM: getVoiceMailNUmber: " + number);
241                     return number;
242                 });
243     }
244 
getVoiceMailAlphaTag(String callingPackage, String callingFeatureId)245     public String getVoiceMailAlphaTag(String callingPackage, String callingFeatureId) {
246         return getVoiceMailAlphaTagForSubscriber(getDefaultSubscription(), callingPackage,
247                 callingFeatureId);
248     }
249 
getVoiceMailAlphaTagForSubscriber(int subId, String callingPackage, String callingFeatureId)250     public String getVoiceMailAlphaTagForSubscriber(int subId, String callingPackage,
251             String callingFeatureId) {
252         return callPhoneMethodForSubIdWithReadCheck(subId, callingPackage, callingFeatureId,
253                 "getVoiceMailAlphaTag", (phone)-> phone.getVoiceMailAlphaTag());
254     }
255 
256     /**
257      * get Phone object based on subId.
258      **/
259     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
getPhone(int subId)260     private Phone getPhone(int subId) {
261         int phoneId = SubscriptionManager.getPhoneId(subId);
262         if (!SubscriptionManager.isValidPhoneId(phoneId)) {
263             return null;
264         }
265         return PhoneFactory.getPhone(phoneId);
266     }
267 
enforceIccSimChallengeResponsePermission(Context context, int subId, String callingPackage, String callingFeatureId, String message)268     private boolean enforceIccSimChallengeResponsePermission(Context context, int subId,
269             String callingPackage, String callingFeatureId, String message) {
270         if (TelephonyPermissions.checkCallingOrSelfUseIccAuthWithDeviceIdentifier(context,
271                 callingPackage, callingFeatureId, message)) {
272             return true;
273         }
274         if (VDBG) log("No USE_ICC_AUTH_WITH_DEVICE_IDENTIFIER permission.");
275         enforcePrivilegedPermissionOrCarrierPrivilege(subId, message);
276         return true;
277     }
278 
279     /**
280      * Make sure caller has either read privileged phone permission or carrier privilege.
281      *
282      * @throws SecurityException if the caller does not have the required permission/privilege
283      */
enforcePrivilegedPermissionOrCarrierPrivilege(int subId, String message)284     private void enforcePrivilegedPermissionOrCarrierPrivilege(int subId, String message) {
285         // TODO(b/73660190): Migrate to
286         // TelephonyPermissions.enforceCallingOrSelfModifyPermissionOrCarrierPrivileges and delete
287         // this helper method.
288         int permissionResult = mContext.checkCallingOrSelfPermission(
289                 READ_PRIVILEGED_PHONE_STATE);
290         if (permissionResult == PackageManager.PERMISSION_GRANTED) {
291             return;
292         }
293         if (VDBG) log("No read privileged phone permission, check carrier privilege next.");
294         TelephonyPermissions.enforceCallingOrSelfCarrierPrivilege(mContext, subId, message);
295     }
296 
297     /**
298      * Make sure caller has modify phone state permission.
299      */
enforceModifyPermission()300     private void enforceModifyPermission() {
301         mContext.enforceCallingOrSelfPermission(MODIFY_PHONE_STATE,
302                 "Requires MODIFY_PHONE_STATE");
303     }
304 
305     /**
306      * Make sure the caller is the calling package itself
307      *
308      * @throws SecurityException if the caller is not the calling package
309      */
enforceCallingPackage(String callingPackage, int callingUid, String message)310     private void enforceCallingPackage(String callingPackage, int callingUid, String message) {
311         int packageUid = -1;
312         PackageManager pm = mContext.createContextAsUser(
313                 UserHandle.getUserHandleForUid(callingUid), 0).getPackageManager();
314         if (pm != null) {
315             try {
316                 packageUid = pm.getPackageUid(callingPackage, 0);
317             } catch (PackageManager.NameNotFoundException e) {
318                 // packageUid is -1
319             }
320         }
321         if (packageUid != callingUid) {
322             throw new SecurityException(message + ": Package " + callingPackage
323                     + " does not belong to " + callingUid);
324         }
325     }
326 
327     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
getDefaultSubscription()328     private int getDefaultSubscription() {
329         return  PhoneFactory.getDefaultSubscription();
330     }
331 
332     /**
333     * get the Isim Impi based on subId
334     */
getIsimImpi(int subId)335     public String getIsimImpi(int subId) {
336         return callPhoneMethodForSubIdWithPrivilegedCheck(subId, "getIsimImpi",
337                 (phone) -> {
338                     IsimRecords isim = phone.getIsimRecords();
339                     if (isim != null) {
340                         return isim.getIsimImpi();
341                     } else {
342                         return null;
343                     }
344                 });
345     }
346 
347     /**
348     * get the Isim Domain based on subId
349     */
350     public String getIsimDomain(int subId) {
351         return callPhoneMethodForSubIdWithPrivilegedCheck(subId, "getIsimDomain",
352                 (phone) -> {
353                     IsimRecords isim = phone.getIsimRecords();
354                     if (isim != null) {
355                         return isim.getIsimDomain();
356                     } else {
357                         return null;
358                     }
359                 });
360     }
361 
362     /**
363     * get the Isim Impu based on subId
364     */
365     public String[] getIsimImpu(int subId) {
366         return callPhoneMethodForSubIdWithPrivilegedCheck(subId, "getIsimImpu",
367                 (phone) -> {
368                     IsimRecords isim = phone.getIsimRecords();
369                     if (isim != null) {
370                         return isim.getIsimImpu();
371                     } else {
372                         return null;
373                     }
374                 });
375     }
376 
377     /**
378     * get the Isim Ist based on subId
379     */
380     public String getIsimIst(int subId) throws RemoteException {
381         return callPhoneMethodForSubIdWithPrivilegedCheck(subId, "getIsimIst",
382                 (phone) -> {
383                     IsimRecords isim = phone.getIsimRecords();
384                     if (isim != null) {
385                         return isim.getIsimIst();
386                     } else {
387                         return null;
388                     }
389                 });
390     }
391 
392     /**
393     * get the Isim Pcscf based on subId
394     */
395     public String[] getIsimPcscf(int subId) throws RemoteException {
396         return callPhoneMethodForSubIdWithPrivilegedCheck(subId, "getIsimPcscf",
397                 (phone) -> {
398                     IsimRecords isim = phone.getIsimRecords();
399                     if (isim != null) {
400                         return isim.getIsimPcscf();
401                     } else {
402                         return null;
403                     }
404                 });
405     }
406 
407     @Override
408     public String getIccSimChallengeResponse(int subId, int appType, int authType, String data,
409             String callingPackage, String callingFeatureId) throws RemoteException {
410         CallPhoneMethodHelper<String> toExecute = (phone)-> {
411             UiccCard uiccCard = phone.getUiccCard();
412             if (uiccCard == null) {
413                 loge("getIccSimChallengeResponse() UiccCard is null");
414                 return null;
415             }
416 
417             UiccCardApplication uiccApp = uiccCard.getApplicationByType(appType);
418             if (uiccApp == null) {
419                 loge("getIccSimChallengeResponse() no app with specified type -- " + appType);
420                 return null;
421             } else {
422                 loge("getIccSimChallengeResponse() found app " + uiccApp.getAid()
423                         + " specified type -- " + appType);
424             }
425 
426             if (authType != UiccCardApplication.AUTH_CONTEXT_EAP_SIM
427                     && authType != UiccCardApplication.AUTH_CONTEXT_EAP_AKA) {
428                 loge("getIccSimChallengeResponse() unsupported authType: " + authType);
429                 return null;
430             }
431             return uiccApp.getIccRecords().getIccSimChallengeResponse(authType, data);
432         };
433 
434         return callPhoneMethodWithPermissionCheck(subId, callingPackage, callingFeatureId,
435                 "getIccSimChallengeResponse", toExecute,
436                 this::enforceIccSimChallengeResponsePermission);
437     }
438 
439     public String getGroupIdLevel1ForSubscriber(int subId, String callingPackage,
440             String callingFeatureId) {
441         return callPhoneMethodForSubIdWithReadCheck(subId, callingPackage, callingFeatureId,
442                 "getGroupIdLevel1", (phone)-> phone.getGroupIdLevel1());
443     }
444 
445     /** Below are utility methods that abstracts the flow that many public methods use:
446      *  1. Check permission: pass, throw exception, or fails (returns false).
447      *  2. clearCallingIdentity.
448      *  3. Call a specified phone method and get return value.
449      *  4. restoreCallingIdentity and return.
450      */
451     private interface CallPhoneMethodHelper<T> {
452         T callMethod(Phone phone);
453     }
454 
455     private interface PermissionCheckHelper {
456         // Implemented to do whatever permission check it wants.
457         // If passes, it should return true.
458         // If permission is not granted, throws SecurityException.
459         // If permission is revoked by AppOps, return false.
460         boolean checkPermission(Context context, int subId, String callingPackage,
461                 @Nullable String callingFeatureId, String message);
462     }
463 
464     // Base utility method that others use.
465     private <T> T callPhoneMethodWithPermissionCheck(int subId, String callingPackage,
466             @Nullable String callingFeatureId, String message,
467             CallPhoneMethodHelper<T> callMethodHelper,
468             PermissionCheckHelper permissionCheckHelper) {
469         if (!permissionCheckHelper.checkPermission(mContext, subId, callingPackage,
470                 callingFeatureId, message)) {
471             return null;
472         }
473 
474         final long identity = Binder.clearCallingIdentity();
475         try {
476             Phone phone = getPhone(subId);
477             if (phone != null) {
478                 return callMethodHelper.callMethod(phone);
479             } else {
480                 loge(message + " phone is null for Subscription:" + subId);
481                 return null;
482             }
483         } finally {
484             Binder.restoreCallingIdentity(identity);
485         }
486     }
487 
488     private <T> T callPhoneMethodForSubIdWithReadCheck(int subId, String callingPackage,
489             @Nullable String callingFeatureId, String message,
490             CallPhoneMethodHelper<T> callMethodHelper) {
491         return callPhoneMethodWithPermissionCheck(subId, callingPackage, callingFeatureId,
492                 message, callMethodHelper,
493                 (aContext, aSubId, aCallingPackage, aCallingFeatureId, aMessage)->
494                         TelephonyPermissions.checkCallingOrSelfReadPhoneState(
495                                 aContext, aSubId, aCallingPackage, aCallingFeatureId, aMessage));
496     }
497 
498     private <T> T callPhoneMethodForSubIdWithReadDeviceIdentifiersCheck(int subId,
499             String callingPackage, @Nullable String callingFeatureId, String message,
500             CallPhoneMethodHelper<T> callMethodHelper) {
501         return callPhoneMethodWithPermissionCheck(subId, callingPackage, callingFeatureId,
502                 message, callMethodHelper,
503                 (aContext, aSubId, aCallingPackage, aCallingFeatureId, aMessage)->
504                         TelephonyPermissions.checkCallingOrSelfReadDeviceIdentifiers(
505                                 aContext, aSubId, aCallingPackage, aCallingFeatureId, aMessage));
506     }
507 
508     private <T> T callPhoneMethodForSubIdWithReadSubscriberIdentifiersCheck(int subId,
509             String callingPackage, @Nullable String callingFeatureId, String message,
510             CallPhoneMethodHelper<T> callMethodHelper) {
511         return callPhoneMethodWithPermissionCheck(subId, callingPackage, callingFeatureId,
512                 message, callMethodHelper,
513                 (aContext, aSubId, aCallingPackage, aCallingFeatureId, aMessage)->
514                         TelephonyPermissions.checkCallingOrSelfReadSubscriberIdentifiers(
515                                 aContext, aSubId, aCallingPackage, aCallingFeatureId, aMessage));
516     }
517 
518     private <T> T callPhoneMethodForSubIdWithPrivilegedCheck(
519             int subId, String message, CallPhoneMethodHelper<T> callMethodHelper) {
520         return callPhoneMethodWithPermissionCheck(subId, null, null, message, callMethodHelper,
521                 (aContext, aSubId, aCallingPackage, aCallingFeatureId, aMessage) -> {
522                     mContext.enforceCallingOrSelfPermission(READ_PRIVILEGED_PHONE_STATE, message);
523                     return true;
524                 });
525     }
526 
527     private <T> T callPhoneMethodForSubIdWithModifyCheck(int subId, String callingPackage,
528             String message, CallPhoneMethodHelper<T> callMethodHelper) {
529         return callPhoneMethodWithPermissionCheck(subId, null, null, message, callMethodHelper,
530                 (aContext, aSubId, aCallingPackage, aCallingFeatureId, aMessage)-> {
531                     enforceModifyPermission();
532                     return true;
533                 });
534     }
535 
536     private <T> T callPhoneMethodForSubIdWithReadPhoneNumberCheck(int subId, String callingPackage,
537             @NonNull String callingFeatureId, String message,
538             CallPhoneMethodHelper<T> callMethodHelper) {
539         return callPhoneMethodWithPermissionCheck(subId, callingPackage, callingFeatureId,
540                 message, callMethodHelper,
541                 (aContext, aSubId, aCallingPackage, aCallingFeatureId, aMessage) ->
542                         TelephonyPermissions.checkCallingOrSelfReadPhoneNumber(
543                                 aContext, aSubId, aCallingPackage, aCallingFeatureId, aMessage));
544     }
545 
546     private <T> T callPhoneMethodForPhoneIdWithReadDeviceIdentifiersCheck(int phoneId,
547             String callingPackage, @Nullable String callingFeatureId, String message,
548             CallPhoneMethodHelper<T> callMethodHelper) {
549         // Getting subId before doing permission check.
550         if (!SubscriptionManager.isValidPhoneId(phoneId)) {
551             phoneId = 0;
552         }
553         final Phone phone = PhoneFactory.getPhone(phoneId);
554         if (phone == null) {
555             return null;
556         }
557         if (!TelephonyPermissions.checkCallingOrSelfReadDeviceIdentifiers(mContext,
558                 phone.getSubId(), callingPackage, callingFeatureId, message)) {
559             return null;
560         }
561 
562         final long identity = Binder.clearCallingIdentity();
563         try {
564             return callMethodHelper.callMethod(phone);
565         } finally {
566             Binder.restoreCallingIdentity(identity);
567         }
568     }
569 
570     private void log(String s) {
571         Rlog.d(TAG, s);
572     }
573 
574     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
575     private void loge(String s) {
576         Rlog.e(TAG, s);
577     }
578 }
579