Android10设置ProfileOwner失败的源码解析
ProfileOwner的设置可以通过反射DevicePolicyManager中的方法,直接将当前或者指定的用户下的程序设置为ProfileOwner。
但是Android9都是有效的,到Android10却不生效了,报错信息为:
IllegalStateException: Unable to set non-default profile owner post-setup ...
为什么会报这个错误呢,来看看源码中什么情况会报这个错误。
DevicePolicyManager中有两个方法都可以设置ProfileOwner,分别是setProfileOwner、setActiveProfileOwner。
setProfileOwner可以将DeviceAdmin设置为ProfileOwner。
setActiveProfileOwner可以将普通用户设置为ProfileOwner。
分别来看看两个方法的源码:
setProfileOwner:
public boolean setProfileOwner(@NonNull ComponentName admin, @Deprecated String ownerName,
int userHandle) throws IllegalArgumentException {
if (mService != null) {
try {
if (ownerName == null) {
ownerName = "";
}
return mService.setProfileOwner(admin, ownerName, userHandle);
} catch (RemoteException re) {
throw re.rethrowFromSystemServer();
}
}
return false;
}
可以看到直接使用了mService.setProfileOwner(admin, ownerName, userHandle)进行设置,其中userHandle是由方法传入的,所以可以设置指定的用户设置为ProfileOwner。
setActiveProfileOwner:
public boolean setActiveProfileOwner(@NonNull ComponentName admin, @Deprecated String ownerName)
throws IllegalArgumentException {
throwIfParentInstance("setActiveProfileOwner");
if (mService != null) {
try {
final int myUserId = myUserId();
mService.setActiveAdmin(admin, false, myUserId);
return mService.setProfileOwner(admin, ownerName, myUserId);
} catch (RemoteException re) {
throw re.rethrowFromSystemServer();
}
}
return false;
}
这是一个打有@Deprecated的方法,是废弃的,主要做了三件事,第一件事是获取当前用户id,第二件事是将当前用户设置为DeviceAdmin,第三件事是将当前用户设置为ProfileOwner,同样设置ProfileOwner的方法是mService.setProfileOwner(admin, ownerName, myUserId)。
两种方式都是使用mService的setProfileOwner方法,接下来看看setProfileOwner方法的实现。
setProfileOwner具体实现是在DevicePolicyManagerService.java中,这是frameworks层代码,可以去源码网站查看。
@Override
public boolean setProfileOwner(ComponentName who, String ownerName, int userHandle) {
if (!mHasFeature) {
return false;
}
if (who == null
|| !isPackageInstalledForUser(who.getPackageName(), userHandle)) {
throw new IllegalArgumentException("Component " + who
+ " not installed for userId:" + userHandle);
}
final boolean hasIncompatibleAccountsOrNonAdb =
hasIncompatibleAccountsOrNonAdbNoLock(userHandle, who);
synchronized (getLockObject()) {
enforceCanSetProfileOwnerLocked(who, userHandle, hasIncompatibleAccountsOrNonAdb);
...
}
到目前为止,Android9与Android10差别不大,在setProfileOwner方法中,会先进入到enforceCanSetProfileOwnerLocked方法,而引起Android10报错的代码就在这个方法中。
来看看Android9中enforceCanSetProfileOwnerLocked代码的实现:
private void enforceCanSetProfileOwnerLocked(@Nullable ComponentName owner, int userHandle,
boolean hasIncompatibleAccountsOrNonAdb) {
UserInfo info = getUserInfo(userHandle);
if (info == null) {
// User doesn't exist.
throw new IllegalArgumentException(
"Attempted to set profile owner for invalid userId: " + userHandle);
}
if (info.isGuest()) {
throw new IllegalStateException("Cannot set a profile owner on a guest");
}
if (mOwners.hasProfileOwner(userHandle)) {
throw new IllegalStateException("Trying to set the profile owner, but profile owner "
+ "is already set.");
}
if (mOwners.hasDeviceOwner() && mOwners.getDeviceOwnerUserId() == userHandle) {
throw new IllegalStateException("Trying to set the profile owner, but the user "
+ "already has a device owner.");
}
if (isAdb()) {
if ((mIsWatch || hasUserSetupCompleted(userHandle))
&& hasIncompatibleAccountsOrNonAdb) {
throw new IllegalStateException("Not allowed to set the profile owner because "
+ "there are already some accounts on the profile");
}
return;
}
enforceCanManageProfileAndDeviceOwners();
if ((mIsWatch || hasUserSetupCompleted(userHandle)) && !isCallerWithSystemUid()) {
throw new IllegalStateException("Cannot set the profile owner on a user which is "
+ "already set-up");
}
}
Android10中enforceCanSetProfileOwnerLocked代码的实现:
private void enforceCanSetProfileOwnerLocked(@Nullable ComponentName owner, int userHandle,
boolean hasIncompatibleAccountsOrNonAdb) {
UserInfo info = getUserInfo(userHandle);
if (info == null) {
// User doesn't exist.
throw new IllegalArgumentException(
"Attempted to set profile owner for invalid userId: " + userHandle);
}
if (info.isGuest()) {
throw new IllegalStateException("Cannot set a profile owner on a guest");
}
if (mOwners.hasProfileOwner(userHandle)) {
throw new IllegalStateException("Trying to set the profile owner, but profile owner "
+ "is already set.");
}
if (mOwners.hasDeviceOwner() && mOwners.getDeviceOwnerUserId() == userHandle) {
throw new IllegalStateException("Trying to set the profile owner, but the user "
+ "already has a device owner.");
}
if (isAdb()) {
if ((mIsWatch || hasUserSetupCompleted(userHandle))
&& hasIncompatibleAccountsOrNonAdb) {
throw new IllegalStateException("Not allowed to set the profile owner because "
+ "there are already some accounts on the profile");
}
return;
}
enforceCanManageProfileAndDeviceOwners();
if ((mIsWatch || hasUserSetupCompleted(userHandle))) {
if (!isCallerWithSystemUid()) {
throw new IllegalStateException("Cannot set the profile owner on a user which is "
+ "already set-up");
}
if (!mIsWatch) {
// Only the default supervision profile owner can be set as profile owner after SUW
final String supervisor = mContext.getResources().getString(
com.android.internal.R.string
.config_defaultSupervisionProfileOwnerComponent);
if (supervisor == null) {
throw new IllegalStateException("Unable to set profile owner post-setup, no"
+ "default supervisor profile owner defined");
}
final ComponentName supervisorComponent = ComponentName.unflattenFromString(
supervisor);
if (!owner.equals(supervisorComponent)) {
throw new IllegalStateException("Unable to set non-default profile owner"
+ " post-setup " + owner);
}
}
}
}
通过Android9与10的比较可以看处从enforceCanManageProfileAndDeviceOwners()方法以上都是一样的,不一样出在这个方法的下面,并且可以看到Unable to set non-default profile owner post-setup错误是由哪里报出来的。
Android9与10不同的一段就是Android10会多出来一个判断:
if (!mIsWatch) {
// Only the default supervision profile owner can be set as profile owner after SUW
final String supervisor = mContext.getResources().getString(
com.android.internal.R.string
.config_defaultSupervisionProfileOwnerComponent);
if (supervisor == null) {
throw new IllegalStateException("Unable to set profile owner post-setup, no"
+ "default supervisor profile owner defined");
}
final ComponentName supervisorComponent = ComponentName.unflattenFromString(
supervisor);
if (!owner.equals(supervisorComponent)) {
throw new IllegalStateException("Unable to set non-default profile owner"
+ " post-setup " + owner);
}
}
首先mIsWatch是判断是否是穿戴手表类型的设备,是穿戴手表为true,反之为false,那么不是穿戴手表类型的设备会进入到下面的判断。
然后获取config_defaultSupervisionProfileOwnerComponent的String内容,这个String是系统的,获取出来后,会使用这个String生成ComponentName。
ComponentName中unflattenFromString方法:
public static @Nullable ComponentName unflattenFromString(@NonNull String str) {
int sep = str.indexOf('/');
if (sep < 0 || (sep+1) >= str.length()) {
return null;
}
String pkg = str.substring(0, sep);
String cls = str.substring(sep+1);
if (cls.length() > 0 && cls.charAt(0) == '.') {
cls = pkg + cls;
}
return new ComponentName(pkg, cls);
}
根据上面的代码可以推测出config_defaultSupervisionProfileOwnerComponent的内容应该为: com.xxx.xxx/com.xxx.xxx.classname或者com.xxx.xxx/.classname
最后会让两个ComponentName进行比较,ComponentName中equals方法:
@Override
public boolean equals(Object obj) {
try {
if (obj != null) {
ComponentName other = (ComponentName)obj;
// Note: no null checks, because mPackage and mClass can
// never be null.
return mPackage.equals(other.mPackage)
&& mClass.equals(other.mClass);
}
} catch (ClassCastException e) {
}
return false;
}
上面的代码就是将ComponentName的package与class与另外一个进行比较,比较不相同就会报Unable to set non-default profile owner post-setup错误。
根据上面的分析,获取到的config_defaultSupervisionProfileOwnerComponent的内容不是您想要设置的包以及包中的类,所以会报错。
怎么让config_defaultSupervisionProfileOwnerComponent这个值是您想要的值呢,目前是对系统进行修改,没有找到其他的方法,经系统修改值之后,Android10可以顺利的设置ProfileOwner。
本文地址:https://blog.csdn.net/qq_33208587/article/details/114320353
下一篇: springboot自定义过滤器的方法