Android访客模式即guest用户下操作文件管理器里的apk安装是被限制的,且安装时会提示“该用户无法安装未知应用”。现需求是放开此限制且修改不影响平台的EDLA认证。
APK安装限制
安装apk的弹窗提示流程可以跟踪PackageInstaller下的PackageInstallerActivity.java。此处通过unknownSourcesRestrictionSource判断限制了apk安装。
private void checkIfAllowedAndInitiateInstall() {
// Check for install apps user restriction first.
final int installAppsRestrictionSource = mUserManager.getUserRestrictionSource(
UserManager.DISALLOW_INSTALL_APPS, Process.myUserHandle());
if ((installAppsRestrictionSource & UserManager.RESTRICTION_SOURCE_SYSTEM) != 0) {
if (mLocalLOGV) Log.i(TAG, "install not allowed: " + UserManager.DISALLOW_INSTALL_APPS);
showDialogInner(DLG_INSTALL_APPS_RESTRICTED_FOR_USER);
return;
} else if (installAppsRestrictionSource != UserManager.RESTRICTION_NOT_SET) {
if (mLocalLOGV) {
Log.i(TAG, "install not allowed by admin; showing "
+ Settings.ACTION_SHOW_ADMIN_SUPPORT_DETAILS);
}
startActivity(new Intent(Settings.ACTION_SHOW_ADMIN_SUPPORT_DETAILS));
finish();
return;
}
if (mAllowUnknownSources || !isInstallRequestFromUnknownSource(getIntent())) {
if (mLocalLOGV) Log.i(TAG, "install allowed");
initiateInstall();
} else {
// Check for unknown sources restrictions.
final int unknownSourcesRestrictionSource = mUserManager.getUserRestrictionSource(
UserManager.DISALLOW_INSTALL_UNKNOWN_SOURCES, Process.myUserHandle());
final int unknownSourcesGlobalRestrictionSource = mUserManager.getUserRestrictionSource(
UserManager.DISALLOW_INSTALL_UNKNOWN_SOURCES_GLOBALLY, Process.myUserHandle());
final int systemRestriction = UserManager.RESTRICTION_SOURCE_SYSTEM
& (unknownSourcesRestrictionSource | unknownSourcesGlobalRestrictionSource);
if (systemRestriction != 0) {
if (mLocalLOGV) Log.i(TAG, "Showing DLG_UNKNOWN_SOURCES_RESTRICTED_FOR_USER");
showDialogInner(DLG_UNKNOWN_SOURCES_RESTRICTED_FOR_USER);//该用户无法安装未知应用
} else if (unknownSourcesRestrictionSource != UserManager.RESTRICTION_NOT_SET) {
startAdminSupportDetailsActivity(UserManager.DISALLOW_INSTALL_UNKNOWN_SOURCES);
} else if (unknownSourcesGlobalRestrictionSource != UserManager.RESTRICTION_NOT_SET) {
startAdminSupportDetailsActivity(
UserManager.DISALLOW_INSTALL_UNKNOWN_SOURCES_GLOBALLY);
} else {
handleUnknownSources();
}
}
}
由于该认证平台用的/vendor/partner_gms/apps/GooglePackageInstaller,纯apk无源码无法修改,所以需寻找另外一种修改方式来支持。
多用户Restrictions
由以上启发,得知这是一个多用户unknown sources restrictions限制问题。具体源码可以查看:frameworks/base/services/core/java/com/android/server/pm/UserManagerService.java。
1、设置中添加访客,查看系统多用户目录/data/system/users下的文件:
2、我们分别看下多用户列表userlist.xml和访客用户10.xml下的内容:
<?xml version='1.0' encoding='utf-8' standalone='yes' ?>
<users nextSerialNumber="11" version="9" userTypeConfigVersion="0">
<guestRestrictions>
<restrictions no_sms="true" no_install_unknown_sources="true" no_config_wifi="true" no_config_credentials="true" no_outgoing_calls="true" />
</guestRestrictions>
<deviceOwnerUserId id="-10000" />
<user id="0" />
<user id="10" />
</users>
<?xml version='1.0' encoding='utf-8' standalone='yes' ?>
<user id="10" serialNumber="10" flags="1044" type="android.os.usertype.full.GUEST" created="1701933606874" lastLoggedIn="1701933612138" lastLoggedInFingerprint="aa085250b2813ee81e5fd4fa9d7d49f5e05a74c9" profileBadge="0">
<restrictions no_sms="true" no_install_unknown_sources="true" no_config_wifi="true" no_config_credentials="true" no_outgoing_calls="true" />
<device_policy_local_restrictions />
<ignorePrepareStorageErrors>false</ignorePrepareStorageErrors>
</user>
可以得知guestRestrictions已经默认明确了一些访客权限限制,具体可以看下UserManagerService类中的Bundle对象mGuestRestrictions的数据生成过程。
3、我们尝试在访客用户生成时赋予UserManager.DISALLOW_INSTALL_UNKNOWN_SOURCES使用者权限。上层可以监听ACTION_USER_SWITCHED用户切换广播时处理。
其中SystemUI中GuestResumeSessionReceiver已经有了该广播处理过程,修改如下:
if (Intent.ACTION_USER_SWITCHED.equals(action)) {
cancelDialog();
int userId = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, UserHandle.USER_NULL);
if (userId == UserHandle.USER_NULL) {
Log.e(TAG, intent + " sent to " + TAG + " without EXTRA_USER_HANDLE");
return;
}
UserInfo currentUser = mUserTracker.getUserInfo();
if (!currentUser.isGuest()) {
return;
}
int notFirstLogin = mSecureSettings.getIntForUser(
SETTING_GUEST_HAS_LOGGED_IN, 0, userId);
//add by liuke
boolean hasUserRestriction = mUserManager.hasUserRestriction(UserManager.DISALLOW_INSTALL_UNKNOWN_SOURCES, new UserHandle(userId));
Log.i(TAG, "notFirstLogin = " + notFirstLogin + ", userId = " + userId + ", hasUserRestriction = " + hasUserRestriction);
mUserManager.setUserRestriction(UserManager.DISALLOW_INSTALL_UNKNOWN_SOURCES, false, UserHandle.of(userId));
//end by liuke
if (notFirstLogin != 0) {
mNewSessionDialog = new ResetSessionDialog(context, mUserSwitcherController,
mUiEventLogger, userId);
mNewSessionDialog.show();
} else {
mSecureSettings.putIntForUser(SETTING_GUEST_HAS_LOGGED_IN, 1, userId);
}
}