Merge "Add device identifier permission checks to TelephonyPermissions"

am: 1ca89a995b

Change-Id: I7f6d821d6596cf24960b2b136ff03b5e23ca5382
This commit is contained in:
Nazanin Bakhshi
2019-07-01 17:36:49 -07:00
committed by android-build-merger
6 changed files with 374 additions and 28 deletions

View File

@@ -169,6 +169,7 @@ message Atom {
BluetoothSmpPairingEventReported bluetooth_smp_pairing_event_reported = 167;
ProcessStartTime process_start_time = 169;
BluetoothSocketConnectionStateChanged bluetooth_socket_connection_state_changed = 171;
DeviceIdentifierAccessDenied device_identifier_access_denied = 172;
NetworkStackReported network_stack_reported = 182 [(log_from_module) = "network_stack"];
}
@@ -3098,3 +3099,22 @@ message NetworkStackReported {
optional android.stats.connectivity.NetworkStackEventData network_stack_event = 2 [(log_mode) = MODE_BYTES];
}
/**
* Logs when a package is denied access to a device identifier based on the new access requirements.
*
* Logged from:
* frameworks/base/telephony/java/com/android/internal/telephony/TelephonyPermissions.java
*/
message DeviceIdentifierAccessDenied {
// The name of the package denied access to the requested device identifier.
optional string package_name = 1;
// The name of the device identifier method the package attempted to invoke.
optional string method_name = 2;
// True if the package is preinstalled.
optional bool is_preinstalled = 3;
// True if the package is privileged.
optional bool is_priv_app = 4;
}

View File

@@ -5653,6 +5653,31 @@ public class DevicePolicyManager {
return null;
}
/**
* Returns whether the specified package can read the device identifiers.
*
* @param packageName The package name of the app to check for device identifier access.
* @param pid The process id of the package to be checked.
* @param uid The uid of the package to be checked.
* @return whether the package can read the device identifiers.
*
* @hide
*/
public boolean checkDeviceIdentifierAccess(String packageName, int pid, int uid) {
throwIfParentInstance("checkDeviceIdentifierAccess");
if (packageName == null) {
return false;
}
if (mService != null) {
try {
return mService.checkDeviceIdentifierAccess(packageName, pid, uid);
} catch (RemoteException re) {
throw re.rethrowFromSystemServer();
}
}
return false;
}
/**
* @hide
* @return the human readable name of the organisation associated with this DPM or {@code null}

View File

@@ -146,6 +146,7 @@ interface IDevicePolicyManager {
int getDeviceOwnerUserId();
boolean setProfileOwner(in ComponentName who, String ownerName, int userHandle);
ComponentName getProfileOwnerAsUser(int userHandle);
ComponentName getProfileOwner(int userHandle);
String getProfileOwnerName(int userHandle);
void setProfileEnabled(in ComponentName who);
@@ -153,6 +154,8 @@ interface IDevicePolicyManager {
void clearProfileOwner(in ComponentName who);
boolean hasUserSetupCompleted();
boolean checkDeviceIdentifierAccess(in String packageName, int pid, int uid);
void setDeviceOwnerLockScreenInfo(in ComponentName who, CharSequence deviceOwnerInfo);
CharSequence getDeviceOwnerLockScreenInfo();

View File

@@ -15,7 +15,6 @@
*/
package com.android.server.devicepolicy;
import android.annotation.UserIdInt;
import android.app.admin.IDevicePolicyManager;
import android.content.ComponentName;
import android.os.PersistableBundle;
@@ -159,4 +158,9 @@ abstract class BaseIDevicePolicyManager extends IDevicePolicyManager.Stub {
@Override
public void setDefaultSmsApplication(ComponentName admin, String packageName) {
}
@Override
public boolean checkDeviceIdentifierAccess(String packageName, int pid, int uid) {
return false;
}
}

View File

@@ -60,7 +60,6 @@ import static android.app.admin.DevicePolicyManager.WIPE_EUICC;
import static android.app.admin.DevicePolicyManager.WIPE_EXTERNAL_STORAGE;
import static android.app.admin.DevicePolicyManager.WIPE_RESET_PROTECTION_DATA;
import static android.content.pm.PackageManager.MATCH_UNINSTALLED_PACKAGES;
import static android.provider.Telephony.Carriers.DPC_URI;
import static android.provider.Telephony.Carriers.ENFORCE_KEY;
import static android.provider.Telephony.Carriers.ENFORCE_MANAGED_URI;
@@ -69,11 +68,10 @@ import static com.android.internal.logging.nano.MetricsProto.MetricsEvent
.PROVISIONING_ENTRY_POINT_ADB;
import static com.android.internal.widget.LockPatternUtils.StrongAuthTracker
.STRONG_AUTH_REQUIRED_AFTER_DPM_LOCK_NOW;
import static com.android.server.devicepolicy.TransferOwnershipMetadataManager.ADMIN_TYPE_DEVICE_OWNER;
import static com.android.server.devicepolicy.TransferOwnershipMetadataManager.ADMIN_TYPE_PROFILE_OWNER;
import static com.android.server.devicepolicy.TransferOwnershipMetadataManager
.ADMIN_TYPE_DEVICE_OWNER;
import static com.android.server.devicepolicy.TransferOwnershipMetadataManager
.ADMIN_TYPE_PROFILE_OWNER;
import static com.android.server.pm.PackageManagerService.PLATFORM_PACKAGE_NAME;
import static org.xmlpull.v1.XmlPullParser.END_DOCUMENT;
@@ -219,11 +217,11 @@ import com.android.internal.util.FastXmlSerializer;
import com.android.internal.util.FunctionalUtils.ThrowingRunnable;
import com.android.internal.util.JournaledFile;
import com.android.internal.util.Preconditions;
import com.android.internal.util.StatLogger;
import com.android.internal.util.XmlUtils;
import com.android.internal.widget.LockPatternUtils;
import com.android.server.LocalServices;
import com.android.server.LockGuard;
import com.android.internal.util.StatLogger;
import com.android.server.SystemServerInitThreadPool;
import com.android.server.SystemService;
import com.android.server.devicepolicy.DevicePolicyManagerService.ActiveAdmin.TrustAgentInfo;
@@ -5188,7 +5186,8 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
@Override
public void enforceCanManageCaCerts(ComponentName who, String callerPackage) {
if (who == null) {
if (!isCallerDelegate(callerPackage, DELEGATION_CERT_INSTALL)) {
if (!isCallerDelegate(callerPackage, mInjector.binderGetCallingUid(),
DELEGATION_CERT_INSTALL)) {
mContext.enforceCallingOrSelfPermission(MANAGE_CA_CERTIFICATES, null);
}
} else {
@@ -5364,7 +5363,8 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
if (UserHandle.getUserId(callerUid) != mOwners.getDeviceOwnerUserId()) {
throw new SecurityException("Caller not from device owner user");
}
if (!isCallerDelegate(callerPackage, DELEGATION_CERT_INSTALL)) {
if (!isCallerDelegate(callerPackage, mInjector.binderGetCallingUid(),
DELEGATION_CERT_INSTALL)) {
throw new SecurityException("Caller with uid " + mInjector.binderGetCallingUid() +
"has no permission to generate keys.");
}
@@ -5766,15 +5766,14 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
* @param scope the delegation scope to be checked.
* @return {@code true} if the calling process is a delegate of {@code scope}.
*/
private boolean isCallerDelegate(String callerPackage, String scope) {
private boolean isCallerDelegate(String callerPackage, int callerUid, String scope) {
Preconditions.checkNotNull(callerPackage, "callerPackage is null");
if (!Arrays.asList(DELEGATIONS).contains(scope)) {
throw new IllegalArgumentException("Unexpected delegation scope: " + scope);
}
// Retrieve the UID and user ID of the calling process.
final int callingUid = mInjector.binderGetCallingUid();
final int userId = UserHandle.getUserId(callingUid);
final int userId = UserHandle.getUserId(callerUid);
synchronized (getLockObject()) {
// Retrieve user policy data.
final DevicePolicyData policy = getUserData(userId);
@@ -5787,7 +5786,7 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
final int uid = mInjector.getPackageManager()
.getPackageUidAsUser(callerPackage, userId);
// Return true if the caller is actually callerPackage.
return uid == callingUid;
return uid == callerUid;
} catch (NameNotFoundException e) {
// Ignore.
}
@@ -5818,7 +5817,7 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
getActiveAdminForCallerLocked(who, reqPolicy);
}
// If no ComponentName is given ensure calling process has scope delegation.
} else if (!isCallerDelegate(callerPackage, scope)) {
} else if (!isCallerDelegate(callerPackage, mInjector.binderGetCallingUid(), scope)) {
throw new SecurityException("Caller with uid " + mInjector.binderGetCallingUid()
+ " is not a delegate of scope " + scope + ".");
}
@@ -7782,6 +7781,13 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
}
}
@Override
public ComponentName getProfileOwnerAsUser(int userHandle) {
enforceCrossUsersPermission(userHandle);
return getProfileOwner(userHandle);
}
@Override
public ComponentName getProfileOwner(int userHandle) {
if (!mHasFeature) {
@@ -7825,6 +7831,68 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
return getApplicationLabel(profileOwner.getPackageName(), userHandle);
}
@Override
public boolean checkDeviceIdentifierAccess(String packageName, int pid, int uid) {
// If the caller is not a system app then it should only be able to check its own device
// identifier access.
int callingUid = mInjector.binderGetCallingUid();
int callingPid = mInjector.binderGetCallingPid();
if (UserHandle.getAppId(callingUid) >= Process.FIRST_APPLICATION_UID
&& (callingUid != uid || callingPid != pid)) {
String message = String.format(
"Calling uid %d, pid %d cannot check device identifier access for package %s "
+ "(uid=%d, pid=%d)", callingUid, callingPid, packageName, uid, pid);
Log.w(LOG_TAG, message);
throw new SecurityException(message);
}
// Verify that the specified packages matches the provided uid.
int userId = UserHandle.getUserId(uid);
try {
ApplicationInfo appInfo = mIPackageManager.getApplicationInfo(packageName, 0, userId);
// Since this call goes directly to PackageManagerService a NameNotFoundException is not
// thrown but null data can be returned; if the appInfo for the specified package cannot
// be found then return false to prevent crashing the app.
if (appInfo == null) {
Log.w(LOG_TAG,
String.format("appInfo could not be found for package %s", packageName));
return false;
} else if (uid != appInfo.uid) {
String message = String.format("Package %s (uid=%d) does not match provided uid %d",
packageName, appInfo.uid, uid);
Log.w(LOG_TAG, message);
throw new SecurityException(message);
}
} catch (RemoteException e) {
// If an exception is caught obtaining the appInfo just return false to prevent crashing
// apps due to an internal error.
Log.e(LOG_TAG, "Exception caught obtaining appInfo for package " + packageName, e);
return false;
}
// A device or profile owner must also have the READ_PHONE_STATE permission to access device
// identifiers. If the package being checked does not have this permission then deny access.
if (mContext.checkPermission(android.Manifest.permission.READ_PHONE_STATE, pid, uid)
!= PackageManager.PERMISSION_GRANTED) {
return false;
}
// Allow access to the device owner or delegate cert installer.
ComponentName deviceOwner = getDeviceOwnerComponent(true);
if (deviceOwner != null && (deviceOwner.getPackageName().equals(packageName)
|| isCallerDelegate(packageName, uid, DELEGATION_CERT_INSTALL))) {
return true;
}
// Allow access to the profile owner for the specified user, or delegate cert installer
ComponentName profileOwner = getProfileOwnerAsUser(userId);
if (profileOwner != null && (profileOwner.getPackageName().equals(packageName)
|| isCallerDelegate(packageName, uid, DELEGATION_CERT_INSTALL))) {
return true;
}
Log.w(LOG_TAG, String.format("Package %s (uid=%d, pid=%d) cannot access Device IDs",
packageName, uid, pid));
return false;
}
/**
* Canonical name for a given package.
*/
@@ -8266,7 +8334,8 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
@Override
public boolean isCallerApplicationRestrictionsManagingPackage(String callerPackage) {
return isCallerDelegate(callerPackage, DELEGATION_APP_RESTRICTIONS);
return isCallerDelegate(callerPackage, mInjector.binderGetCallingUid(),
DELEGATION_APP_RESTRICTIONS);
}
@Override

View File

@@ -19,17 +19,28 @@ import static android.content.pm.PackageManager.PERMISSION_GRANTED;
import android.Manifest;
import android.app.AppOpsManager;
import android.app.admin.DevicePolicyManager;
import android.content.Context;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.os.Binder;
import android.os.Build;
import android.os.Process;
import android.os.RemoteException;
import android.os.ServiceManager;
import android.os.UserHandle;
import android.telephony.Rlog;
import android.telephony.SubscriptionManager;
import android.telephony.TelephonyManager;
import android.util.Log;
import android.util.StatsLog;
import com.android.internal.annotations.VisibleForTesting;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.function.Supplier;
/** Utility class for Telephony permission enforcement. */
@@ -41,6 +52,20 @@ public final class TelephonyPermissions {
private static final Supplier<ITelephony> TELEPHONY_SUPPLIER = () ->
ITelephony.Stub.asInterface(ServiceManager.getService(Context.TELEPHONY_SERVICE));
/**
* Whether to disable the new device identifier access restrictions.
*/
private static final String PROPERTY_DEVICE_IDENTIFIER_ACCESS_RESTRICTIONS_DISABLED =
"device_identifier_access_restrictions_disabled";
// Contains a mapping of packages that did not meet the new requirements to access device
// identifiers and the methods they were attempting to invoke; used to prevent duplicate
// reporting of packages / methods.
private static final Map<String, Set<String>> sReportedDeviceIDPackages;
static {
sReportedDeviceIDPackages = new HashMap<>();
}
private TelephonyPermissions() {}
/**
@@ -112,6 +137,19 @@ public final class TelephonyPermissions {
context, TELEPHONY_SUPPLIER, subId, pid, uid, callingPackage, message);
}
/**
* Check whether the calling packages has carrier privileges for the passing subscription.
* @return {@code true} if the caller has carrier privileges, {@false} otherwise.
*/
public static boolean checkCarrierPrivilegeForSubId(int subId) {
if (SubscriptionManager.isValidSubscriptionId(subId)
&& getCarrierPrivilegeStatus(TELEPHONY_SUPPLIER, subId, Binder.getCallingUid())
== TelephonyManager.CARRIER_PRIVILEGE_STATUS_HAS_ACCESS) {
return true;
}
return false;
}
@VisibleForTesting
public static boolean checkReadPhoneState(
Context context, Supplier<ITelephony> telephonySupplier, int subId, int pid, int uid,
@@ -179,18 +217,9 @@ public final class TelephonyPermissions {
context.enforcePermission(
android.Manifest.permission.READ_PHONE_STATE, pid, uid, message);
} catch (SecurityException phoneStateException) {
SubscriptionManager sm = (SubscriptionManager) context.getSystemService(
Context.TELEPHONY_SUBSCRIPTION_SERVICE);
int[] activeSubIds = sm.getActiveSubscriptionIdList();
for (int activeSubId : activeSubIds) {
// If we don't have the runtime permission, but do have carrier privileges, that
// suffices for reading phone state.
if (getCarrierPrivilegeStatus(telephonySupplier, activeSubId, uid)
== TelephonyManager.CARRIER_PRIVILEGE_STATUS_HAS_ACCESS) {
return true;
}
}
return false;
// If we don't have the runtime permission, but do have carrier privileges, that
// suffices for reading phone state.
return checkCarrierPrivilegeForAnySubId(context, telephonySupplier, uid);
}
}
@@ -201,6 +230,182 @@ public final class TelephonyPermissions {
AppOpsManager.MODE_ALLOWED;
}
/**
* Check whether the caller (or self, if not processing an IPC) can read device identifiers.
*
* <p>This method behaves in one of the following ways:
* <ul>
* <li>return true: if the caller has the READ_PRIVILEGED_PHONE_STATE permission, the calling
* package passes a DevicePolicyManager Device Owner / Profile Owner device identifier
* access check, or the calling package has carrier privileges.
* <li>throw SecurityException: if the caller does not meet any of the requirements and is
* targeting Q or is targeting pre-Q and does not have the READ_PHONE_STATE permission.
* <li>return false: if the caller is targeting pre-Q and does have the READ_PHONE_STATE
* permission. In this case the caller would expect to have access to the device
* identifiers so false is returned instead of throwing a SecurityException to indicate
* the calling function should return dummy data.
* </ul>
*/
public static boolean checkCallingOrSelfReadDeviceIdentifiers(Context context,
String callingPackage, String message) {
return checkCallingOrSelfReadDeviceIdentifiers(context,
SubscriptionManager.INVALID_SUBSCRIPTION_ID, callingPackage, message);
}
/**
* Check whether the caller (or self, if not processing an IPC) can read device identifiers.
*
* <p>This method behaves in one of the following ways:
* <ul>
* <li>return true: if the caller has the READ_PRIVILEGED_PHONE_STATE permission, the calling
* package passes a DevicePolicyManager Device Owner / Profile Owner device identifier
* access check, or the calling package has carrier privileges.
* <li>throw SecurityException: if the caller does not meet any of the requirements and is
* targeting Q or is targeting pre-Q and does not have the READ_PHONE_STATE permission
* or carrier privileges.
* <li>return false: if the caller is targeting pre-Q and does have the READ_PHONE_STATE
* permission or carrier privileges. In this case the caller would expect to have access
* to the device identifiers so false is returned instead of throwing a SecurityException
* to indicate the calling function should return dummy data.
* </ul>
*/
public static boolean checkCallingOrSelfReadDeviceIdentifiers(Context context, int subId,
String callingPackage, String message) {
return checkReadDeviceIdentifiers(context, TELEPHONY_SUPPLIER, subId,
Binder.getCallingPid(), Binder.getCallingUid(), callingPackage, message);
}
/**
* Check whether the caller (or self, if not processing an IPC) can read subscriber identifiers.
*
* <p>This method behaves in one of the following ways:
* <ul>
* <li>return true: if the caller has the READ_PRIVILEGED_PHONE_STATE permission, the calling
* package passes a DevicePolicyManager Device Owner / Profile Owner device identifier
* access check, or the calling package has carrier privileges.
* <li>throw SecurityException: if the caller does not meet any of the requirements and is
* targeting Q or is targeting pre-Q and does not have the READ_PHONE_STATE permission.
* <li>return false: if the caller is targeting pre-Q and does have the READ_PHONE_STATE
* permission. In this case the caller would expect to have access to the device
* identifiers so false is returned instead of throwing a SecurityException to indicate
* the calling function should return dummy data.
* </ul>
*/
public static boolean checkCallingOrSelfReadSubscriberIdentifiers(Context context, int subId,
String callingPackage, String message) {
return checkReadDeviceIdentifiers(context, TELEPHONY_SUPPLIER, subId,
Binder.getCallingPid(), Binder.getCallingUid(), callingPackage, message);
}
/**
* Checks whether the app with the given pid/uid can read device identifiers.
*
* @returns true if the caller has the READ_PRIVILEGED_PHONE_STATE permission or the calling
* package passes a DevicePolicyManager Device Owner / Profile Owner device identifier access
* check.
*/
@VisibleForTesting
public static boolean checkReadDeviceIdentifiers(Context context,
Supplier<ITelephony> telephonySupplier, int subId, int pid, int uid,
String callingPackage, String message) {
// Allow system and root access to the device identifiers.
final int appId = UserHandle.getAppId(uid);
if (appId == Process.SYSTEM_UID || appId == Process.ROOT_UID) {
return true;
}
// Allow access to packages that have the READ_PRIVILEGED_PHONE_STATE permission.
if (context.checkPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE, pid,
uid) == PackageManager.PERMISSION_GRANTED) {
return true;
}
// If the calling package has carrier privileges for any subscription then allow access.
if (checkCarrierPrivilegeForAnySubId(context, telephonySupplier, uid)) {
return true;
}
// if the calling package is not null then perform the DevicePolicyManager device /
// profile owner and Appop checks.
if (callingPackage != null) {
// Allow access to a device / profile owner app.
DevicePolicyManager devicePolicyManager =
(DevicePolicyManager) context.getSystemService(
Context.DEVICE_POLICY_SERVICE);
if (devicePolicyManager != null && devicePolicyManager.checkDeviceIdentifierAccess(
callingPackage, pid, uid)) {
return true;
}
}
return reportAccessDeniedToReadIdentifiers(context, subId, pid, uid, callingPackage,
message);
}
/**
* Reports a failure when the app with the given pid/uid cannot access the requested identifier.
*
* @returns false if the caller is targeting pre-Q and does have the READ_PHONE_STATE
* permission or carrier privileges.
* @throws SecurityException if the caller does not meet any of the requirements for the
* requested identifier and is targeting Q or is targeting pre-Q
* and does not have the READ_PHONE_STATE permission or carrier
* privileges.
*/
private static boolean reportAccessDeniedToReadIdentifiers(Context context, int subId, int pid,
int uid, String callingPackage, String message) {
boolean isPreinstalled = false;
boolean isPrivApp = false;
ApplicationInfo callingPackageInfo = null;
try {
callingPackageInfo = context.getPackageManager().getApplicationInfoAsUser(
callingPackage, 0, UserHandle.getUserId(uid));
if (callingPackageInfo != null) {
if (callingPackageInfo.isSystemApp()) {
isPreinstalled = true;
if (callingPackageInfo.isPrivilegedApp()) {
isPrivApp = true;
}
}
}
} catch (PackageManager.NameNotFoundException e) {
// If the application info for the calling package could not be found then assume the
// calling app is a non-preinstalled app to detect any issues with the check
Log.e(LOG_TAG, "Exception caught obtaining package info for package " + callingPackage,
e);
}
// The current package should only be reported in StatsLog if it has not previously been
// reported for the currently invoked device identifier method.
boolean packageReported = sReportedDeviceIDPackages.containsKey(callingPackage);
if (!packageReported || !sReportedDeviceIDPackages.get(callingPackage).contains(
message)) {
Set invokedMethods;
if (!packageReported) {
invokedMethods = new HashSet<String>();
sReportedDeviceIDPackages.put(callingPackage, invokedMethods);
} else {
invokedMethods = sReportedDeviceIDPackages.get(callingPackage);
}
invokedMethods.add(message);
StatsLog.write(StatsLog.DEVICE_IDENTIFIER_ACCESS_DENIED, callingPackage, message,
isPreinstalled, isPrivApp);
}
Log.w(LOG_TAG, "reportAccessDeniedToReadIdentifiers:" + callingPackage + ":" + message
+ ":isPreinstalled=" + isPreinstalled + ":isPrivApp=" + isPrivApp);
// if the target SDK is pre-Q then check if the calling package would have previously
// had access to device identifiers.
if (callingPackageInfo != null && (
callingPackageInfo.targetSdkVersion < Build.VERSION_CODES.Q)) {
if (context.checkPermission(
android.Manifest.permission.READ_PHONE_STATE,
pid,
uid) == PackageManager.PERMISSION_GRANTED) {
return false;
}
if (checkCarrierPrivilegeForSubId(subId)) {
return false;
}
}
throw new SecurityException(message + ": The user " + uid
+ " does not meet the requirements to access device identifiers.");
}
/**
* Check whether the app with the given pid/uid can read the call log.
* @return {@code true} if the specified app has the read call log permission and AppOpp granted
@@ -383,6 +588,26 @@ public final class TelephonyPermissions {
}
}
/**
* Returns whether the provided uid has carrier privileges for any active subscription ID.
*/
private static boolean checkCarrierPrivilegeForAnySubId(Context context,
Supplier<ITelephony> telephonySupplier, int uid) {
SubscriptionManager sm = (SubscriptionManager) context.getSystemService(
Context.TELEPHONY_SUBSCRIPTION_SERVICE);
int[] activeSubIds = sm.getActiveSubscriptionIdList();
if (activeSubIds != null) {
for (int activeSubId : activeSubIds) {
if (getCarrierPrivilegeStatus(telephonySupplier, activeSubId, uid)
== TelephonyManager.CARRIER_PRIVILEGE_STATUS_HAS_ACCESS) {
return true;
}
}
}
return false;
}
private static int getCarrierPrivilegeStatus(
Supplier<ITelephony> telephonySupplier, int subId, int uid) {
ITelephony telephony = telephonySupplier.get();