Android 哪些系统应用没法禁用(即哪些应用的禁用按钮是灰选)?
环境:Android S 12 源码
frameworks/base/packages/SettingsLib/src/com/android/settingslib/Utils.java
/**
* Determine whether a package is a "system package", in which case certain things (like
* disabling notifications or disabling the package altogether) should be disallowed.
*/
public static boolean isSystemPackage(Resources resources, PackageManager pm, PackageInfo pkg) {
if (sSystemSignature == null) {
sSystemSignature = new Signature[]{getSystemSignature(pm)};
}
if (sPermissionControllerPackageName == null) {
sPermissionControllerPackageName = pm.getPermissionControllerPackageName();
}
if (sServicesSystemSharedLibPackageName == null) {
sServicesSystemSharedLibPackageName = pm.getServicesSystemSharedLibraryPackageName();
}
if (sSharedSystemSharedLibPackageName == null) {
sSharedSystemSharedLibPackageName = pm.getSharedSystemSharedLibraryPackageName();
}
return (sSystemSignature[0] != null
&& sSystemSignature[0].equals(getFirstSignature(pkg)))
|| pkg.packageName.equals(sPermissionControllerPackageName)
|| pkg.packageName.equals(sServicesSystemSharedLibPackageName)
|| pkg.packageName.equals(sSharedSystemSharedLibPackageName)
|| pkg.packageName.equals(PrintManager.PRINT_SPOOLER_PACKAGE_NAME)
|| isDeviceProvisioningPackage(resources, pkg.packageName);
}
private static Signature getFirstSignature(PackageInfo pkg) {
if (pkg != null && pkg.signatures != null && pkg.signatures.length > 0) {
return pkg.signatures[0];
}
return null;
}
private static Signature getSystemSignature(PackageManager pm) {
try {
final PackageInfo sys = pm.getPackageInfo("android", PackageManager.GET_SIGNATURES);
return getFirstSignature(sys);
} catch (NameNotFoundException e) {
}
return null;
}
/**
* Returns {@code true} if the supplied package is the device provisioning app. Otherwise,
* returns {@code false}.
*/
public static boolean isDeviceProvisioningPackage(Resources resources, String packageName) {
String deviceProvisioningPackage = resources.getString(
com.android.internal.R.string.config_deviceProvisioningPackage);
return deviceProvisioningPackage != null && deviceProvisioningPackage.equals(packageName);
}
case1:与"android"包对比签名信息
private static Signature getSystemSignature(PackageManager pm) {
try {
final PackageInfo sys = pm.getPackageInfo("android", PackageManager.GET_SIGNATURES);
return getFirstSignature(sys);
} catch (NameNotFoundException e) {
}
return null;
}
case2:pm.getPermissionControllerPackageName()
PackageManagerService.java
@Override
public String getPermissionControllerPackageName() {
synchronized (mLock) {
if (mRequiredPermissionControllerPackage != null) {
final PackageSetting ps = getPackageSetting(mRequiredPermissionControllerPackage);
if (ps != null) {
final int callingUid = Binder.getCallingUid();
final int callingUserId = UserHandle.getUserId(callingUid);
if (!shouldFilterApplicationLocked(ps, callingUid, callingUserId)) {
return mRequiredPermissionControllerPackage;
}
}
}
throw new IllegalStateException("PermissionController is not found");
}
}
mRequiredPermissionControllerPackage 变量由下面方法赋值
private @NonNull String getRequiredPermissionControllerLPr() {
final Intent intent = new Intent(Intent.ACTION_MANAGE_PERMISSIONS);
intent.addCategory(Intent.CATEGORY_DEFAULT);
final List<ResolveInfo> matches = queryIntentActivitiesInternal(intent, null,
MATCH_SYSTEM_ONLY | MATCH_DIRECT_BOOT_AWARE | MATCH_DIRECT_BOOT_UNAWARE,
UserHandle.USER_SYSTEM);
if (matches.size() == 1) {
ResolveInfo resolveInfo = matches.get(0);
if (!resolveInfo.activityInfo.applicationInfo.isPrivilegedApp()) {
throw new RuntimeException("The permissions manager must be a privileged app");
}
return matches.get(0).getComponentInfo().packageName;
} else {
throw new RuntimeException("There must be exactly one permissions manager; found "
+ matches);
}
}
public static final String ACTION_MANAGE_PERMISSIONS = "android.intent.action.MANAGE_PERMISSIONS";
示例:mainline包的permissioncontroller (com.google.android.permissioncontroller) 默认是无法被禁用的,即按钮默认是灰选的
反编译 permissioncontroller
<manifest xmlns:android="http://schemas.android.com/apk/res/android" android:versionCode="301501400" android:versionName="r_aml_301501400" android:compileSdkVersion="30" android:compileSdkVersionCodename="11" coreApp="true" package="com.google.android.permissioncontroller" platformBuildVersionCode="30" platformBuildVersionName="11">
<application android:theme="@style/FilterTouches" android:label="@string/app_name" android:icon="@drawable/ic_permission_controller_app_icon" android:name="com.android.permissioncontroller.PermissionControllerApplication" android:allowClearUserData="false" android:allowBackup="false" android:supportsRtl="true" android:extractNativeLibs="false" android:defaultToDeviceProtectedStorage="true" android:directBootAware="true" android:appComponentFactory="androidx.core.app.CoreComponentFactory" android:forceQueryable="true">
<activity android:theme="@style/Settings_FilterTouches" android:label="@string/app_permissions" android:name="com.android.permissioncontroller.permission.ui.ManagePermissionsActivity" android:permission="android.permission.GRANT_RUNTIME_PERMISSIONS" android:configChanges="keyboardHidden|orientation|screenSize">
<intent-filter android:priority="1">
<action android:name="android.intent.action.MANAGE_APP_PERMISSIONS"/>
<action android:name="android.intent.action.MANAGE_APP_PERMISSION"/>
<action android:name="android.intent.action.MANAGE_PERMISSION_APPS"/>
<action android:name="android.intent.action.MANAGE_PERMISSIONS"/>
<action android:name="android.intent.action.REVIEW_PERMISSION_USAGE"/>
<category android:name="android.intent.category.DEFAULT"/>
</intent-filter>
</activity>
application标签存在 directBootAware 属性,能够匹配 上面的 queryIntentActivitiesInternal 方法。
case3:pm.getServicesSystemSharedLibraryPackageName()
@Override
public @NonNull String getServicesSystemSharedLibraryPackageName() {
// allow instant applications
synchronized (mLock) {
return mServicesExtensionPackageName;
}
}
......
mServicesExtensionPackageName = getRequiredServicesExtensionPackageLPr();
......
@NonNull
private String getRequiredServicesExtensionPackageLPr() {
String servicesExtensionPackage =
ensureSystemPackageName(
mContext.getString(R.string.config_servicesExtensionPackage));
if (TextUtils.isEmpty(servicesExtensionPackage)) {
throw new RuntimeException(
"Required services extension package is missing, check "
+ "config_servicesExtensionPackage.");
}
return servicesExtensionPackage;
}
......
frameworks/base/core/res/res/values/config.xml
<!-- Package name of the required service extension package. -->
<string name="config_servicesExtensionPackage" translatable="false">android.ext.services</string>
......
@Nullable
private String ensureSystemPackageName(@Nullable String packageName) {
if (packageName == null) {
return null;
}
final long token = Binder.clearCallingIdentity();
try {
if (getPackageInfo(packageName, MATCH_FACTORY_ONLY, UserHandle.USER_SYSTEM) == null) {
PackageInfo packageInfo = getPackageInfo(packageName, 0, UserHandle.USER_SYSTEM);
if (packageInfo != null) {
EventLog.writeEvent(0x534e4554, "145981139", packageInfo.applicationInfo.uid,
"");
}
return null;
}
} finally {
Binder.restoreCallingIdentity(token);
}
return packageName;
}
case4:pm.getSharedSystemSharedLibraryPackageName()
@Override
public @NonNull String getSharedSystemSharedLibraryPackageName() {
// allow instant applications
synchronized (mLock) {
return mSharedSystemSharedLibraryPackageName;
}
}
......
mSharedSystemSharedLibraryPackageName = getRequiredSharedLibraryLPr(
PackageManager.SYSTEM_SHARED_LIBRARY_SHARED,
SharedLibraryInfo.VERSION_UNDEFINED);
......
public static final String SYSTEM_SHARED_LIBRARY_SHARED = "android.ext.shared";
示例:GMS包的GoogleExtShared.apk (com.google.android.ext.shared) 默认是无法被禁用的,即按钮默认是灰选的
反编译 GoogleExtShared.apk
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android" android:versionCode="1" android:versionName="1" android:compileSdkVersion="30" android:compileSdkVersionCodename="11" coreApp="true" package="com.google.android.ext.shared" platformBuildVersionCode="30" platformBuildVersionName="11">
<uses-sdk android:minSdkVersion="30" android:targetSdkVersion="30"/>
<application android:label="@string/app_name" android:allowBackup="false" android:extractNativeLibs="true" android:defaultToDeviceProtectedStorage="true" android:directBootAware="true">
<library android:name="android.ext.shared"/>
</application>
</manifest>
(Partner-Facing) Google Product Geo-Availability Chart on Android v3 (MADA Partners)(1).xlsx