Protect Device Identifiers behind priv permission and DO/PO checks
Bug: 110099294
Test: cts-tradefed run cts -m CtsDevicePolicyManagerTestCases \
-t com.android.cts.devicepolicy.DeviceOwnerTest.testDeviceOwnerCanGetDeviceIdentifiers
Test: cts-tradefed run cts -m CtsDevicePolicyManagerTestCases \
-t com.android.cts.devicepolicy.ManagedProfileTest#testGetDeviceIdentifiers
Test: cts-tradefed run cts -m CtsTelephonyTestCases -t android.telephony.cts.TelephonyManagerTest
Test: cts-tradefed run cts -m CtsPermissionTestCases -t android.permission.cts.TelephonyManagerPermissionTest
Change-Id: I3c82c53ec89cd17b34a61166ccc9e9747388efac
This commit is contained in:
@@ -5702,6 +5702,37 @@ 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.
|
||||
* @return whether the package can read the device identifiers.
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
public boolean checkDeviceIdentifierAccess(String packageName) {
|
||||
return checkDeviceIdentifierAccessAsUser(packageName, myUserId());
|
||||
}
|
||||
|
||||
/**
|
||||
* @hide
|
||||
*/
|
||||
@RequiresPermission(value = android.Manifest.permission.MANAGE_USERS, conditional = true)
|
||||
public boolean checkDeviceIdentifierAccessAsUser(String packageName, int userId) {
|
||||
throwIfParentInstance("checkDeviceIdentifierAccessAsUser");
|
||||
if (packageName == null) {
|
||||
return false;
|
||||
}
|
||||
if (mService != null) {
|
||||
try {
|
||||
return mService.checkDeviceIdentifierAccess(packageName, userId);
|
||||
} catch (RemoteException re) {
|
||||
throw re.rethrowFromSystemServer();
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Called by a profile owner or device owner to set a default activity that the system selects
|
||||
* to handle intents that match the given {@link IntentFilter}. This activity will remain the
|
||||
|
||||
@@ -153,6 +153,8 @@ interface IDevicePolicyManager {
|
||||
void clearProfileOwner(in ComponentName who);
|
||||
boolean hasUserSetupCompleted();
|
||||
|
||||
boolean checkDeviceIdentifierAccess(in String packageName, int userHandle);
|
||||
|
||||
void setDeviceOwnerLockScreenInfo(in ComponentName who, CharSequence deviceOwnerInfo);
|
||||
CharSequence getDeviceOwnerLockScreenInfo();
|
||||
|
||||
|
||||
@@ -18,8 +18,10 @@ package android.os;
|
||||
|
||||
import android.Manifest;
|
||||
import android.annotation.RequiresPermission;
|
||||
import android.annotation.SuppressAutoDoc;
|
||||
import android.annotation.SystemApi;
|
||||
import android.annotation.TestApi;
|
||||
import android.app.ActivityThread;
|
||||
import android.app.Application;
|
||||
import android.content.Context;
|
||||
import android.text.TextUtils;
|
||||
@@ -127,14 +129,21 @@ public class Build {
|
||||
* <a href="/training/articles/security-key-attestation.html">key attestation</a> to obtain
|
||||
* proof of the device's original identifiers.
|
||||
*
|
||||
* <p>Requires Permission: READ_PRIVILEGED_PHONE_STATE or for the calling package to be the
|
||||
* device or profile owner. Profile owner access is deprecated and will be removed in a future
|
||||
* release.
|
||||
*
|
||||
* @return The serial number if specified.
|
||||
*/
|
||||
@RequiresPermission(Manifest.permission.READ_PHONE_STATE)
|
||||
@SuppressAutoDoc // No support for device / profile owner.
|
||||
@RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
|
||||
public static String getSerial() {
|
||||
IDeviceIdentifiersPolicyService service = IDeviceIdentifiersPolicyService.Stub
|
||||
.asInterface(ServiceManager.getService(Context.DEVICE_IDENTIFIERS_SERVICE));
|
||||
try {
|
||||
return service.getSerial();
|
||||
Application application = ActivityThread.currentApplication();
|
||||
String callingPackage = application != null ? application.getPackageName() : null;
|
||||
return service.getSerialForPackage(callingPackage);
|
||||
} catch (RemoteException e) {
|
||||
e.rethrowFromSystemServer();
|
||||
}
|
||||
|
||||
@@ -21,4 +21,5 @@ package android.os;
|
||||
*/
|
||||
interface IDeviceIdentifiersPolicyService {
|
||||
String getSerial();
|
||||
String getSerialForPackage(in String callingPackage);
|
||||
}
|
||||
@@ -16,6 +16,7 @@
|
||||
|
||||
package com.android.bandwidthtest;
|
||||
|
||||
import android.app.UiAutomation;
|
||||
import android.content.Context;
|
||||
import android.net.ConnectivityManager;
|
||||
import android.net.NetworkInfo.State;
|
||||
@@ -74,7 +75,13 @@ public class BandwidthTest extends InstrumentationTestCase {
|
||||
Log.v(LOG_TAG, "Initialized mConnectionUtil");
|
||||
mUid = Process.myUid();
|
||||
mTManager = (TelephonyManager)mContext.getSystemService(Context.TELEPHONY_SERVICE);
|
||||
mDeviceId = mTManager.getDeviceId();
|
||||
final UiAutomation uiAutomation = getInstrumentation().getUiAutomation();
|
||||
try {
|
||||
uiAutomation.adoptShellPermissionIdentity();
|
||||
mDeviceId = mTManager.getDeviceId();
|
||||
} finally {
|
||||
uiAutomation.dropShellPermissionIdentity();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -322,6 +322,7 @@ applications that come with the platform
|
||||
<permission name="android.permission.PACKAGE_USAGE_STATS" />
|
||||
<permission name="android.permission.READ_FRAME_BUFFER"/>
|
||||
<permission name="android.permission.READ_LOWPAN_CREDENTIAL"/>
|
||||
<permission name="android.permission.READ_PRIVILEGED_PHONE_STATE"/>
|
||||
<permission name="android.permission.REAL_GET_TASKS"/>
|
||||
<permission name="android.permission.REGISTER_CALL_PROVIDER"/>
|
||||
<permission name="android.permission.REGISTER_CONNECTION_MANAGER"/>
|
||||
|
||||
@@ -16,18 +16,15 @@
|
||||
|
||||
package com.android.server.os;
|
||||
|
||||
import android.Manifest;
|
||||
import android.annotation.NonNull;
|
||||
import android.annotation.Nullable;
|
||||
import android.content.Context;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.os.Binder;
|
||||
import android.os.Build;
|
||||
import android.os.IDeviceIdentifiersPolicyService;
|
||||
import android.os.Process;
|
||||
import android.os.RemoteException;
|
||||
import android.os.SystemProperties;
|
||||
import android.os.UserHandle;
|
||||
|
||||
import com.android.internal.telephony.TelephonyPermissions;
|
||||
import com.android.server.SystemService;
|
||||
|
||||
/**
|
||||
@@ -54,15 +51,22 @@ public final class DeviceIdentifiersPolicyService extends SystemService {
|
||||
|
||||
@Override
|
||||
public @Nullable String getSerial() throws RemoteException {
|
||||
if (UserHandle.getAppId(Binder.getCallingUid()) != Process.SYSTEM_UID
|
||||
&& mContext.checkCallingOrSelfPermission(
|
||||
Manifest.permission.READ_PHONE_STATE)
|
||||
!= PackageManager.PERMISSION_GRANTED
|
||||
&& mContext.checkCallingOrSelfPermission(
|
||||
Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
|
||||
!= PackageManager.PERMISSION_GRANTED) {
|
||||
throw new SecurityException("getSerial requires READ_PHONE_STATE"
|
||||
+ " or READ_PRIVILEGED_PHONE_STATE permission");
|
||||
// Since this invocation is on the server side a null value is used for the
|
||||
// callingPackage as the server's package name (typically android) should not be used
|
||||
// for any device / profile owner checks. The majority of requests for the serial number
|
||||
// should use the getSerialForPackage method with the calling package specified.
|
||||
if (!TelephonyPermissions.checkCallingOrSelfReadDeviceIdentifiers(mContext,
|
||||
/* callingPackage */ null, "getSerial")) {
|
||||
return null;
|
||||
}
|
||||
return SystemProperties.get("ro.serialno", Build.UNKNOWN);
|
||||
}
|
||||
|
||||
@Override
|
||||
public @Nullable String getSerialForPackage(String callingPackage) throws RemoteException {
|
||||
if (!TelephonyPermissions.checkCallingOrSelfReadDeviceIdentifiers(mContext,
|
||||
callingPackage, "getSerial")) {
|
||||
return null;
|
||||
}
|
||||
return SystemProperties.get("ro.serialno", Build.UNKNOWN);
|
||||
}
|
||||
|
||||
@@ -66,4 +66,9 @@ abstract class BaseIDevicePolicyManager extends IDevicePolicyManager.Stub {
|
||||
public long forceSecurityLogs() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean checkDeviceIdentifierAccess(String packageName, int userHandle) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7861,6 +7861,21 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
|
||||
return getApplicationLabel(profileOwner.getPackageName(), userHandle);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean checkDeviceIdentifierAccess(String packageName, int userHandle) {
|
||||
// Allow access to the device owner.
|
||||
ComponentName deviceOwner = getDeviceOwnerComponent(true);
|
||||
if (deviceOwner != null && deviceOwner.getPackageName().equals(packageName)) {
|
||||
return true;
|
||||
}
|
||||
// Allow access to the profile owner for the specified user.
|
||||
ComponentName profileOwner = getProfileOwnerAsUser(userHandle);
|
||||
if (profileOwner != null && profileOwner.getPackageName().equals(packageName)) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Canonical name for a given package.
|
||||
*/
|
||||
|
||||
@@ -1268,15 +1268,18 @@ public class TelephonyManager {
|
||||
* Returns the unique device ID, for example, the IMEI for GSM and the MEID
|
||||
* or ESN for CDMA phones. Return null if device ID is not available.
|
||||
*
|
||||
* <p>Requires Permission: {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE}
|
||||
* or that the calling app has carrier privileges (see {@link #hasCarrierPrivileges}).
|
||||
* <p>Requires Permission: READ_PRIVILEGED_PHONE_STATE or for the calling package to be the
|
||||
* device or profile owner. The profile owner is an app that owns a managed profile on the
|
||||
* device; for more details see <a href="https://developer.android.com/work/managed-profiles">
|
||||
* Work profiles</a>. Profile owner access is deprecated and will be removed in a future
|
||||
* release.
|
||||
*
|
||||
* @deprecated Use (@link getImei} which returns IMEI for GSM or (@link getMeid} which returns
|
||||
* MEID for CDMA.
|
||||
*/
|
||||
@Deprecated
|
||||
@SuppressAutoDoc // Blocked by b/72967236 - no support for carrier privileges
|
||||
@RequiresPermission(android.Manifest.permission.READ_PHONE_STATE)
|
||||
@SuppressAutoDoc // No support for device / profile owner.
|
||||
@RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
|
||||
public String getDeviceId() {
|
||||
try {
|
||||
ITelephony telephony = getITelephony();
|
||||
@@ -1294,8 +1297,11 @@ public class TelephonyManager {
|
||||
* Returns the unique device ID of a subscription, for example, the IMEI for
|
||||
* GSM and the MEID for CDMA phones. Return null if device ID is not available.
|
||||
*
|
||||
* <p>Requires Permission: {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE}
|
||||
* or that the calling app has carrier privileges (see {@link #hasCarrierPrivileges}).
|
||||
* <p>Requires Permission: READ_PRIVILEGED_PHONE_STATE or for the calling package to be the
|
||||
* device or profile owner. The profile owner is an app that owns a managed profile on the
|
||||
* device; for more details see <a href="https://developer.android.com/work/managed-profiles">
|
||||
* Work profiles</a>. Profile owner access is deprecated and will be removed in a future
|
||||
* release.
|
||||
*
|
||||
* @param slotIndex of which deviceID is returned
|
||||
*
|
||||
@@ -1303,8 +1309,8 @@ public class TelephonyManager {
|
||||
* MEID for CDMA.
|
||||
*/
|
||||
@Deprecated
|
||||
@SuppressAutoDoc // Blocked by b/72967236 - no support for carrier privileges
|
||||
@RequiresPermission(android.Manifest.permission.READ_PHONE_STATE)
|
||||
@SuppressAutoDoc // No support for device / profile owner.
|
||||
@RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
|
||||
public String getDeviceId(int slotIndex) {
|
||||
// FIXME this assumes phoneId == slotIndex
|
||||
try {
|
||||
@@ -1323,11 +1329,14 @@ public class TelephonyManager {
|
||||
* Returns the IMEI (International Mobile Equipment Identity). Return null if IMEI is not
|
||||
* available.
|
||||
*
|
||||
* <p>Requires Permission: {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE}
|
||||
* or that the calling app has carrier privileges (see {@link #hasCarrierPrivileges}).
|
||||
* <p>Requires Permission: READ_PRIVILEGED_PHONE_STATE or for the calling package to be the
|
||||
* device or profile owner. The profile owner is an app that owns a managed profile on the
|
||||
* device; for more details see <a href="https://developer.android.com/work/managed-profiles">
|
||||
* Work profiles</a>. Profile owner access is deprecated and will be removed in a future
|
||||
* release.
|
||||
*/
|
||||
@SuppressAutoDoc // Blocked by b/72967236 - no support for carrier privileges
|
||||
@RequiresPermission(android.Manifest.permission.READ_PHONE_STATE)
|
||||
@SuppressAutoDoc // No support for device / profile owner.
|
||||
@RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
|
||||
public String getImei() {
|
||||
return getImei(getSlotIndex());
|
||||
}
|
||||
@@ -1336,13 +1345,16 @@ public class TelephonyManager {
|
||||
* Returns the IMEI (International Mobile Equipment Identity). Return null if IMEI is not
|
||||
* available.
|
||||
*
|
||||
* <p>Requires Permission: {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE}
|
||||
* or that the calling app has carrier privileges (see {@link #hasCarrierPrivileges}).
|
||||
* <p>Requires Permission: READ_PRIVILEGED_PHONE_STATE or for the calling package to be the
|
||||
* device or profile owner. The profile owner is an app that owns a managed profile on the
|
||||
* device; for more details see <a href="https://developer.android.com/work/managed-profiles">
|
||||
* Work profiles</a>. Profile owner access is deprecated and will be removed in a future
|
||||
* release.
|
||||
*
|
||||
* @param slotIndex of which IMEI is returned
|
||||
*/
|
||||
@SuppressAutoDoc // Blocked by b/72967236 - no support for carrier privileges
|
||||
@RequiresPermission(android.Manifest.permission.READ_PHONE_STATE)
|
||||
@SuppressAutoDoc // No support for device / profile owner.
|
||||
@RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
|
||||
public String getImei(int slotIndex) {
|
||||
ITelephony telephony = getITelephony();
|
||||
if (telephony == null) return null;
|
||||
@@ -1386,11 +1398,14 @@ public class TelephonyManager {
|
||||
/**
|
||||
* Returns the MEID (Mobile Equipment Identifier). Return null if MEID is not available.
|
||||
*
|
||||
* <p>Requires Permission: {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE}
|
||||
* or that the calling app has carrier privileges (see {@link #hasCarrierPrivileges}).
|
||||
* <p>Requires Permission: READ_PRIVILEGED_PHONE_STATE or for the calling package to be the
|
||||
* device or profile owner. The profile owner is an app that owns a managed profile on the
|
||||
* device; for more details see <a href="https://developer.android.com/work/managed-profiles">
|
||||
* Work profiles</a>. Profile owner access is deprecated and will be removed in a future
|
||||
* release.
|
||||
*/
|
||||
@SuppressAutoDoc // Blocked by b/72967236 - no support for carrier privileges
|
||||
@RequiresPermission(android.Manifest.permission.READ_PHONE_STATE)
|
||||
@SuppressAutoDoc // No support for device / profile owner.
|
||||
@RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
|
||||
public String getMeid() {
|
||||
return getMeid(getSlotIndex());
|
||||
}
|
||||
@@ -1398,13 +1413,16 @@ public class TelephonyManager {
|
||||
/**
|
||||
* Returns the MEID (Mobile Equipment Identifier). Return null if MEID is not available.
|
||||
*
|
||||
* <p>Requires Permission: {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE}
|
||||
* or that the calling app has carrier privileges (see {@link #hasCarrierPrivileges}).
|
||||
* <p>Requires Permission: READ_PRIVILEGED_PHONE_STATE or for the calling package to be the
|
||||
* device or profile owner. The profile owner is an app that owns a managed profile on the
|
||||
* device; for more details see <a href="https://developer.android.com/work/managed-profiles">
|
||||
* Work profiles</a>. Profile owner access is deprecated and will be removed in a future
|
||||
* release.
|
||||
*
|
||||
* @param slotIndex of which MEID is returned
|
||||
*/
|
||||
@SuppressAutoDoc // Blocked by b/72967236 - no support for carrier privileges
|
||||
@RequiresPermission(android.Manifest.permission.READ_PHONE_STATE)
|
||||
@SuppressAutoDoc // No support for device / profile owner.
|
||||
@RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
|
||||
public String getMeid(int slotIndex) {
|
||||
ITelephony telephony = getITelephony();
|
||||
if (telephony == null) return null;
|
||||
@@ -2888,11 +2906,15 @@ public class TelephonyManager {
|
||||
* Returns the serial number of the SIM, if applicable. Return null if it is
|
||||
* unavailable.
|
||||
*
|
||||
* <p>Requires Permission: {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE}
|
||||
* or that the calling app has carrier privileges (see {@link #hasCarrierPrivileges}).
|
||||
* <p>Requires Permission: READ_PRIVILEGED_PHONE_STATE, for the calling app to be the device or
|
||||
* profile owner, or that the calling app has carrier privileges (see {@link
|
||||
* #hasCarrierPrivileges}). The profile owner is an app that owns a managed profile on the
|
||||
* device; for more details see <a href="https://developer.android.com/work/managed-profiles">
|
||||
* Work profiles</a>. Profile owner access is deprecated and will be removed in a future
|
||||
* release.
|
||||
*/
|
||||
@SuppressAutoDoc // Blocked by b/72967236 - no support for carrier privileges
|
||||
@RequiresPermission(android.Manifest.permission.READ_PHONE_STATE)
|
||||
@RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
|
||||
public String getSimSerialNumber() {
|
||||
return getSimSerialNumber(getSubId());
|
||||
}
|
||||
@@ -2900,11 +2922,18 @@ public class TelephonyManager {
|
||||
/**
|
||||
* Returns the serial number for the given subscription, if applicable. Return null if it is
|
||||
* unavailable.
|
||||
* <p>
|
||||
*
|
||||
* <p>Requires Permission: READ_PRIVILEGED_PHONE_STATE, for the calling app to be the device or
|
||||
* profile owner, or that the calling app has carrier privileges (see {@link
|
||||
* #hasCarrierPrivileges}). The profile owner is an app that owns a managed profile on the
|
||||
* device; for more details see <a href="https://developer.android.com/work/managed-profiles">
|
||||
* Work profiles</a>. Profile owner access is deprecated and will be removed in a future
|
||||
* release.
|
||||
*
|
||||
* @param subId for which Sim Serial number is returned
|
||||
* @hide
|
||||
*/
|
||||
@RequiresPermission(android.Manifest.permission.READ_PHONE_STATE)
|
||||
@RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
|
||||
@UnsupportedAppUsage
|
||||
public String getSimSerialNumber(int subId) {
|
||||
try {
|
||||
@@ -3039,11 +3068,15 @@ public class TelephonyManager {
|
||||
* Returns the unique subscriber ID, for example, the IMSI for a GSM phone.
|
||||
* Return null if it is unavailable.
|
||||
*
|
||||
* <p>Requires Permission: {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE}
|
||||
* or that the calling app has carrier privileges (see {@link #hasCarrierPrivileges}).
|
||||
* <p>Requires Permission: READ_PRIVILEGED_PHONE_STATE, for the calling app to be the device or
|
||||
* profile owner, or that the calling app has carrier privileges (see {@link
|
||||
* #hasCarrierPrivileges}). The profile owner is an app that owns a managed profile on the
|
||||
* device; for more details see <a href="https://developer.android.com/work/managed-profiles">
|
||||
* Work profiles</a>. Profile owner access is deprecated and will be removed in a future
|
||||
* release.
|
||||
*/
|
||||
@SuppressAutoDoc // Blocked by b/72967236 - no support for carrier privileges
|
||||
@RequiresPermission(android.Manifest.permission.READ_PHONE_STATE)
|
||||
@RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
|
||||
public String getSubscriberId() {
|
||||
return getSubscriberId(getSubId());
|
||||
}
|
||||
@@ -3053,10 +3086,17 @@ public class TelephonyManager {
|
||||
* for a subscription.
|
||||
* Return null if it is unavailable.
|
||||
*
|
||||
* <p>Requires Permission: READ_PRIVILEGED_PHONE_STATE, for the calling app to be the device or
|
||||
* profile owner, or that the calling app has carrier privileges (see {@link
|
||||
* #hasCarrierPrivileges}). The profile owner is an app that owns a managed profile on the
|
||||
* device; for more details see <a href="https://developer.android.com/work/managed-profiles">
|
||||
* Work profiles</a>. Profile owner access is deprecated and will be removed in a future
|
||||
* release.
|
||||
*
|
||||
* @param subId whose subscriber id is returned
|
||||
* @hide
|
||||
*/
|
||||
@RequiresPermission(android.Manifest.permission.READ_PHONE_STATE)
|
||||
@RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
|
||||
@UnsupportedAppUsage
|
||||
public String getSubscriberId(int subId) {
|
||||
try {
|
||||
|
||||
@@ -19,11 +19,16 @@ 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;
|
||||
@@ -134,6 +139,169 @@ 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 or the
|
||||
* calling package passes a DevicePolicyManager Device Owner / Profile Owner device
|
||||
* identifier access check,
|
||||
* <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 or the
|
||||
* calling package passes a DevicePolicyManager Device Owner / Profile Owner device
|
||||
* identifier access check,
|
||||
* <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) {
|
||||
int pid = Binder.getCallingPid();
|
||||
int uid = Binder.getCallingUid();
|
||||
// if the device identifier check completes successfully then grant access.
|
||||
if (checkReadDeviceIdentifiers(context, pid, uid, callingPackage)) {
|
||||
return true;
|
||||
}
|
||||
// else the calling package is not authorized to access the device identifiers; call
|
||||
// a central method to report the failure based on the target SDK and if the calling package
|
||||
// has the READ_PHONE_STATE permission or carrier privileges that were previously required
|
||||
// to access the identifiers.
|
||||
return reportAccessDeniedToReadIdentifiers(context, subId, pid, uid, 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 privleges.
|
||||
* <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) {
|
||||
int pid = Binder.getCallingPid();
|
||||
int uid = Binder.getCallingUid();
|
||||
// if the device identifiers can be read then grant access to the subscriber identifiers
|
||||
if (checkReadDeviceIdentifiers(context, pid, uid, callingPackage)) {
|
||||
return true;
|
||||
}
|
||||
// If the calling package has carrier privileges then allow access to the subscriber
|
||||
// identifiers.
|
||||
if (SubscriptionManager.isValidSubscriptionId(subId) && getCarrierPrivilegeStatus(
|
||||
TELEPHONY_SUPPLIER, subId, uid)
|
||||
== TelephonyManager.CARRIER_PRIVILEGE_STATUS_HAS_ACCESS) {
|
||||
return true;
|
||||
}
|
||||
return reportAccessDeniedToReadIdentifiers(context, subId, pid, uid, 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.
|
||||
*/
|
||||
private static boolean checkReadDeviceIdentifiers(Context context, int pid, int uid,
|
||||
String callingPackage) {
|
||||
// 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 is null then return now as there's no way to perform the
|
||||
// DevicePolicyManager device / profile owner checks.
|
||||
if (callingPackage == null) {
|
||||
return false;
|
||||
}
|
||||
// Allow access to a device / profile owner app.
|
||||
DevicePolicyManager devicePolicyManager = (DevicePolicyManager) context.getSystemService(
|
||||
Context.DEVICE_POLICY_SERVICE);
|
||||
if (devicePolicyManager != null && devicePolicyManager.checkDeviceIdentifierAccessAsUser(
|
||||
callingPackage, Binder.getCallingUserHandle().getIdentifier())) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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) {
|
||||
if (callingPackage != null) {
|
||||
try {
|
||||
// if the target SDK is pre-Q then check if the calling package would have
|
||||
// previously had access to device identifiers.
|
||||
ApplicationInfo callingPackageInfo = context.getPackageManager().getApplicationInfo(
|
||||
callingPackage, 0);
|
||||
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 (SubscriptionManager.isValidSubscriptionId(subId)
|
||||
&& getCarrierPrivilegeStatus(TELEPHONY_SUPPLIER, subId, uid)
|
||||
== TelephonyManager.CARRIER_PRIVILEGE_STATUS_HAS_ACCESS) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
} catch (PackageManager.NameNotFoundException e) {
|
||||
// If the application info for the calling package could not be found then default
|
||||
// to throwing the SecurityException.
|
||||
}
|
||||
}
|
||||
throw new SecurityException(message + ": The user " + uid + " does not have the "
|
||||
+ "READ_PRIVILEGED_PHONE_STATE permission to access the 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
|
||||
|
||||
Reference in New Issue
Block a user