测试平台
Platform: RK3399/RK3328
OS: Android9.0
现象
点击恢复出场设置,应用崩溃。
分析
这是因为系统提供了FRP(google的账户锁,全称factory reset protection,在android 5.x以后释放的功能,避免手机被盗)
FRP和正常FactoryReset的差别
首先,我们要理解信任回复和非信任回复的差别,在Android中,回复出厂设置可以分为:可信任回复 && 不可信任回复:
可信任恢复出场设置方式: 在setting界面中选择恢复出厂设置
不可信任恢复出场设置方式: 通过其余方式(比如recovery双清分区,抑或远程通过google账户登录google play servicer清除用户数据等)都为不可信任回复
该功能的意义在于,当手机丢失,用户可登陆google账号进行数据清除,由于远程为不可信任清除,所以 Android会在开机引导界面setupwirzd处会要求验证google账户来确定机主身份,负责不能跳过这个界面,等于软件性的变砖
而功能上他是由android.service.persistentdata.PersistentDataBlockManager提供接口,在frameworks/base/services/core/java/com/android/server/PersistentDataBlockService.java中进行功能实现的。
查看代码可知手机是否属于信任恢复的状态是存在Account Data Blocks中的,其实就是一个独立的存储分区(500kb),该分区在fatctory reset时不能进入,是通过系统中的ro.frp.pst来制定该分区的路劲。由于我们的设备没有开启frp功能,所以ro.frp.pst为null.
解决
修复补丁如下,当frp未开启时不初始化PersistentDataBlockManager
diff --git a/packages/apps/Settings/src/com/android/settings/MasterClearConfirm.java b/packages/apps/Settings/src/com/android/settings/MasterClearConfirm.java
index a92c8f8..8972787 100644
--- a/packages/apps/Settings/src/com/android/settings/MasterClearConfirm.java
+++ b/packages/apps/Settings/src/com/android/settings/MasterClearConfirm.java
@@ -24,6 +24,7 @@ import android.os.AsyncTask;
import android.os.Bundle;
import android.os.UserHandle;
import android.os.UserManager;
+import android.os.SystemProperties;
import android.service.oemlock.OemLockManager;
import android.service.persistentdata.PersistentDataBlockManager;
import android.view.LayoutInflater;
@@ -31,6 +32,7 @@ import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.TextView;
+import android.text.TextUtils;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
import com.android.settings.core.InstrumentedFragment;
@@ -67,10 +69,20 @@ public class MasterClearConfirm extends InstrumentedFragment {
return;
}
- final PersistentDataBlockManager pdbManager = (PersistentDataBlockManager)
+ final PersistentDataBlockManager pdbManager;
+ final OemLockManager oemLockManager;
+
+ boolean hasPdb = !TextUtils.isEmpty(SystemProperties.get(“ro.frp.pst”));
+ if(hasPdb){
+ pdbManager= (PersistentDataBlockManager)
getActivity().getSystemService(Context.PERSISTENT_DATA_BLOCK_SERVICE);
- final OemLockManager oemLockManager = (OemLockManager)
+
+ oemLockManager = (OemLockManager)
getActivity().getSystemService(Context.OEM_LOCK_SERVICE);
+ }else{
+ pdbManager = null;
+ oemLockManager = null;
+ }
if (pdbManager != null && !oemLockManager.isOemUnlockAllowed() &&
Utils.isDeviceProvisioned(getActivity())) {