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