Aosp13中,TelephonyManager中的getImei()方法是私有权限,禁止提供给第三方使用的。那么我们怎样删除约束使其第三方应用也可以直接使用呢,我们在Aosp13上做分析
一实现:
telephony/java/android/telephony/TelephonyManager.java下
。。。。。。。。。。。。省略
/**
* Returns the IMEI (International Mobile Equipment Identity). Return null if IMEI is not
* available.
*
* See {@link #getImei(int)} for details on the required permissions and behavior
* when the caller does not hold sufficient permissions.
*/
@RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE)//要求系统权限(该权限不对外开放需系统应用才可以)
@RequiresFeature(PackageManager.FEATURE_TELEPHONY_GSM)//要求通话设备
@SuppressAutoDoc // No support for device / profile owner or carrier privileges (b/72967236).
public String getImei() {
return getImei(getSlotIndex());
}
/**
* Returns the IMEI (International Mobile Equipment Identity). Return null if IMEI is not
* available.
*
* <p>Starting with API level 29, persistent device identifiers are guarded behind additional
* restrictions, and apps are recommended to use resettable identifiers (see <a
* href="/training/articles/user-data-ids">Best practices for unique identifiers</a>). This
* method can be invoked if one of the following requirements is met:
* <ul>
* <li>If the calling app has been granted the READ_PRIVILEGED_PHONE_STATE permission; this
* is a privileged permission that can only be granted to apps preloaded on the device.
* <li>If the calling app is the device owner of a fully-managed device, a profile
* owner of an organization-owned device, or their delegates (see {@link
* android.app.admin.DevicePolicyManager#getEnrollmentSpecificId()}).
* <li>If the calling app has carrier privileges (see {@link #hasCarrierPrivileges}) on any
* active subscription.
* <li>If the calling app is the default SMS role holder (see {@link
* RoleManager#isRoleHeld(String)}).
* <li>If the calling app has been granted the
* {@link Manifest.permission#USE_ICC_AUTH_WITH_DEVICE_IDENTIFIER} permission.
* </ul>
*
* <p>If the calling app does not meet one of these requirements then this method will behave
* as follows:
*
* <ul>
* <li>If the calling app's target SDK is API level 28 or lower and the app has the
* READ_PHONE_STATE permission then null is returned.</li>
* <li>If the calling app's target SDK is API level 28 or lower and the app does not have
* the READ_PHONE_STATE permission, or if the calling app is targeting API level 29 or
* higher, then a SecurityException is thrown.</li>
* </ul>
*
* @param slotIndex of which IMEI is returned
* @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
@RequiresFeature(PackageManager.FEATURE_TELEPHONY_GSM)
*/
@SuppressAutoDoc // No support for device / profile owner or carrier privileges (b/72967236).
public String getImei(int slotIndex) {
ITelephony telephony = getITelephony();
if (telephony == null) return null;
try {
Log.d(TAG, "getMeid: slotIndex:" + slotIndex+",getOpPackageName:" + getOpPackageName()+",getAttributionTag:" +getAttributionTag());
return telephony.getImeiForSlot(slotIndex, getOpPackageName(), getAttributionTag());
} catch (RemoteException ex) {
return null;
} catch (NullPointerException ex) {
return null;
}
}
。。。。。。。。。。。省略
二 权限校验处理
以上代码看到getImei()方法顶部有注解约束,将其删除
rootdir/packages/service/Telephony/src/com/android/phone/PhoneInterfaceManager.java下
....
@Override
public String getImeiForSlot(int slotIndex, String callingPackage, String callingFeatureId) {
Phone phone = PhoneFactory.getPhone(slotIndex);
if (phone == null) {
return null;
}
// int subId = phone.getSubId();
// enforceCallingPackage(callingPackage, Binder.getCallingUid(), "getImeiForSlot");
// if (!TelephonyPermissions.checkCallingOrSelfReadDeviceIdentifiers(mApp, subId,
// callingPackage, callingFeatureId, "getImeiForSlot")) {
// return null;
// }
final long identity = Binder.clearCallingIdentity();
try {
return phone.getImei();
} finally {
Binder.restoreCallingIdentity(identity);
}
}
.....
如上图,将约束校验删除
三更新api
我做编译的时候提示异常如下
public class Gesture implements android.os.Parcelable {
@@ -43471,8 +43482,8 @@ public class TelephonyManager {
method @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE) public String[] getForbiddenPlmns();
method @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE) public String getGroupIdLevel1();
method public String getIccAuthentication(int, int, String);
- method @RequiresPermission("android.permission.READ_PRIVILEGED_PHONE_STATE") public String getImei();
- method @RequiresPermission("android.permission.READ_PRIVILEGED_PHONE_STATE") public String getImei(int);
+ method public String getImei();
+ method public String getImei(int);
method @Deprecated @RequiresPermission(anyOf={android.Manifest.permission.READ_PHONE_STATE, android.Manifest.permission.READ_SMS, android.Manifest.permission.READ_PHONE_NUMBERS}) public String getLine1Number();
method @NonNull @RequiresPermission(android.Manifest.permission.READ_PRECISE_PHONE_STATE) public String getManualNetworkSelectionPlmn();
method @Nullable public String getManufacturerCode();
-e
******************************
You have tried to change the API from what has been previously approved.
To make these errors go away, you have two choices:
1. You can add '@hide' javadoc comments (and remove @SystemApi/@TestApi/etc)
to the new methods, etc. shown in the above diff.
2. You can update current.txt and/or removed.txt by executing the following command:
m api-stubs-docs-non-updatable-update-current-api
To submit the revised current.txt to the main Android repository,
you will need approval.
******************************
需要做api更新 指令如图所示
m api-stubs-docs-non-updatable-update-current-api
四然后编译
OVER~
ps:
和同事沟通该问题,同事提出一个新的方案
1:
查看设置模块中获取imei传递的参数,根据第三方包名做判断,传入setting包名,使用setting的参数获取imei返回
2:使用aidl自定义服务,封装getimei方法。实现
---------日后尝试,当前方案是放开全局,风险未知