知识储备

1、恢复出厂接口调用

从系统设置中重置页面入手,很容易找到

packages/apps/Settings/src/com/android/settings/MasterClearConfirm.java

其实就是发送 ACTION_FACTORY_RESET 广播,通知 framework 进行重置,所以我们的工具也可以调用

    private void doMasterClear() {Intent intent = new Intent(Intent.ACTION_FACTORY_RESET);intent.setPackage("android");intent.addFlags(Intent.FLAG_RECEIVER_FOREGROUND);intent.putExtra(Intent.EXTRA_REASON, "MasterClearConfirm");intent.putExtra(Intent.EXTRA_WIPE_EXTERNAL_STORAGE, mEraseSdCard);intent.putExtra(Intent.EXTRA_WIPE_ESIMS, mEraseEsims);getActivity().sendBroadcast(intent);// Intent handling is asynchronous -- assume it will happen soon.}

2、nvram 区域累加次数

由于需要记录实际恢复出厂的次数,所以首选 nvram 存储,回复出厂将清除一切用户数据。

关于 nvram 存储,你可以新加节点或者使用现有节点都行,这里我就偷懒了使用 PRODUCT_INFO 节点存储。

新增节点的方法可参考这篇

android10.0(Q) Nvram 新增节点

上代码

1、在 packages/app/ 下新建 RecoverTool 目录, 增加 Android.mk, 引入 nvram 读写 jar 包

LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_STATIC_JAVA_LIBRARIES += vendor.mediatek.hardware.nvram-V1.0-java
LOCAL_MODULE_TAGS :=  optional
LOCAL_SRC_FILES := $(call all-subdir-java-files)
LOCAL_PACKAGE_NAME := RecoverTool
LOCAL_PRIVATE_PLATFORM_APIS := true
LOCAL_CERTIFICATE := platform
#LOCAL_SDK_VERSION := current
include $(BUILD_PACKAGE)

2、新建 AndroidManifest.xml,增加恢复出厂权限

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"package="com.android.qrdc"android:sharedUserId="android.uid.system"><uses-permission android:name="android.permission.MASTER_CLEAR" /><uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" /><application android:label="@string/app_name" ><activity android:name=".NVActivity"android:label="@string/app_name"><intent-filter><action android:name="android.intent.action.MAIN" /><category android:name="android.intent.category.LAUNCHER" /></intent-filter></activity><receiver android:name="com.android.qrdc.MyStateReceiver"><intent-filter android:priority="1000"><action android:name="android.intent.action.BOOT_COMPLETED" /></intent-filter></receiver></application>
</manifest>

3、在 src/com/android/qrdc 目录下新增 NVActivity.java

一开始在收到开机广播后,然后去读取 nvram 中保存值,发现一直异常,无法成功读取。

从报错的log来看大致是有两个进程同时操作 nvram 对应 binder,后来加了延时去读取发现依旧是一样的问题。

后来又想的办法是,收到开机广播后台拉起 NVActivity,在界面中延迟读取写入,这条路可行。

正好这样拉起界面来也能显示当前记录的次数。

package com.android.qrdc;import android.app.Activity;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.EditText;
import android.widget.TextView;
import android.text.TextUtils;
import android.content.Intent;import java.util.ArrayList;
import java.util.Arrays;
import android.os.Handler;
import android.os.Looper;import vendor.mediatek.hardware.nvram.V1_0.INvram;
import com.android.internal.util.HexDump;public class NVActivity extends Activity {private static final String TAG = "NVActivity";private TextView tv_result,tv_resetcount;private EditText cmdEt,regEt,idPath;private static int ADDRESS_OFFSET = 0;private static void log(String msg) {Log.e("NVActivity", msg);}@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.nv_layout);tv_result = findViewById(R.id.tv_result);tv_resetcount = findViewById(R.id.tv_resetcount);cmdEt = findViewById(R.id.cmdEt);regEt = findViewById(R.id.regEt);idPath = findViewById(R.id.idPath);//tv_resetcount.setText("current reset count="+ readData());new Handler(Looper.getMainLooper()).postDelayed(new Runnable() {@Overridepublic void run() {// doReadNV();autoDoReset();}}, 3000);}private void doMasterClear() {Intent intent = new Intent(Intent.ACTION_FACTORY_RESET);intent.setPackage("android");intent.addFlags(Intent.FLAG_RECEIVER_FOREGROUND);intent.putExtra(Intent.EXTRA_REASON, "NVActivity");intent.putExtra(Intent.EXTRA_WIPE_EXTERNAL_STORAGE, false);intent.putExtra(Intent.EXTRA_WIPE_ESIMS, false);sendBroadcast(intent);// Intent handling is asynchronous -- assume it will happen soon.}public void doReset(View v) {log("doReset click");int nvCount = readData();writeData(++nvCount);doMasterClear();}private void autoDoReset(){ADDRESS_OFFSET = Integer.parseInt(regEt.getText().toString());String newIdPath =  idPath.getText().toString();if (!TextUtils.isEmpty(newIdPath)) {PRODUCT_INFO_FILENAME = newIdPath;}int nvCount = readData();tv_resetcount.setText("current reset count="+ nvCount);writeData(++nvCount);doMasterClear();}public void readNv(View v) {log("readNv click");ADDRESS_OFFSET = Integer.parseInt(regEt.getText().toString());String newIdPath =  idPath.getText().toString();if (!TextUtils.isEmpty(newIdPath)) {PRODUCT_INFO_FILENAME = newIdPath;}tv_result.setText("read result="+ readData());}public void writeNv(View v) {String cmd = cmdEt.getText().toString();ADDRESS_OFFSET = Integer.parseInt(regEt.getText().toString());log("writeNv click -----" + cmd);String newIdPath =  idPath.getText().toString();if (!TextUtils.isEmpty(newIdPath)) {PRODUCT_INFO_FILENAME = newIdPath;}writeData(Integer.parseInt(cmd));}@Overrideprotected void onDestroy() {super.onDestroy();}public static  String PRODUCT_INFO_FILENAME = "/mnt/vendor/nvdata/APCFG/APRDEB/PRODUCT_INFO";private static  void writeData(int n) {byte[] write_buff = new byte[]{0, 0, 0, 0};byte[] by = getBytes(n);for (int i = 0; i < 4; i++) {write_buff[i] = by[i];}try {INvram agent = INvram.getService();if (agent != null) {ArrayList<Byte> dataArray = new ArrayList<>(4);for (byte b : write_buff) {dataArray.add(new Byte(b));}int ret_1 = agent.writeFileByNamevec(PRODUCT_INFO_FILENAME, ADDRESS_OFFSET, dataArray);if (ret_1>0){log("write success"+ ret_1);}else {log("write failed"+ ret_1);}} else {Log.e(TAG, "writeData: agent null");}} catch (Exception e) {Log.e(TAG, "writeData exception:" + e.getLocalizedMessage());e.printStackTrace();}}private static  byte[] getBytes(int data) {byte[] bytes = new byte[4];bytes[0] = (byte) (data & 0xff);bytes[1] = (byte) ((data & 0xff00) >> 8);bytes[2] = (byte) ((data & 0xff0000) >> 16);bytes[3] = (byte) ((data & 0xff000000) >> 24);return bytes;}public static  int readData() {int targets = 0;try {String buff = null;INvram agent = INvram.getService();Log.i(TAG, "readData from PRODUCT_INFO_FILENAME");if (agent != null) {buff = agent.readFileByName(PRODUCT_INFO_FILENAME, ADDRESS_OFFSET);//10}byte[] buffArr = HexDump.hexStringToByteArray(buff.substring(0, buff.length() - 1));targets = (buffArr[0] & 0xff) | ((buffArr[1] << 8) & 0xff00) | ((buffArr[2] << 24) >>> 8) | (buffArr[3] << 24);Log.i(TAG, "readData: buffArr=" + Arrays.toString(buffArr) + ", targets == " + targets);} catch (Exception e) {Log.e(TAG, "readData exception:" + e.getLocalizedMessage());e.printStackTrace();}return targets;}
}

4、增加对应的布局文件 nv_layout.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"android:layout_width="match_parent"android:layout_height="match_parent"android:layout_marginTop="20dp"android:orientation="vertical"><TextViewandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:gravity="top|center_horizontal"android:textSize="22sp"android:text="pwd  " /><EditTextandroid:id="@+id/regEt"android:layout_width="150dp"android:layout_height="wrap_content"android:text="100" /><EditTextandroid:id="@+id/idPath"android:layout_width="wrap_content"android:layout_height="wrap_content"android:text="/mnt/vendor/nvdata/APCFG/APRDEB/PRODUCT_INFO" /><LinearLayoutandroid:layout_width="match_parent"android:layout_height="wrap_content"android:orientation="horizontal"><EditTextandroid:id="@+id/cmdEt"android:layout_width="0dp"android:layout_height="wrap_content"android:layout_weight="1"android:text="10" /><Buttonandroid:id="@+id/write"android:layout_width="0dp"android:layout_height="wrap_content"android:layout_gravity="center"android:layout_weight="1"android:onClick="writeNv"android:text="writeNv" /><Buttonandroid:id="@+id/read"android:layout_width="0dp"android:layout_height="wrap_content"android:layout_gravity="center"android:layout_weight="1"android:onClick="readNv"android:text="readNv" /><Buttonandroid:id="@+id/reset"android:layout_width="0dp"android:layout_height="wrap_content"android:layout_gravity="center"android:layout_weight="1"android:onClick="doReset"android:text="reset" /></LinearLayout><TextViewandroid:id="@+id/tv_result"android:layout_width="wrap_content"android:layout_height="wrap_content"android:textSize="30sp"android:text="this is test text"/><TextViewandroid:id="@+id/tv_resetcount"android:layout_width="wrap_content"android:layout_height="wrap_content"android:textSize="30sp"android:text="current reset count="/>
</LinearLayout>

5、增加 MyStateReceiver 监听开机广播 BOOT_COMPLETED

package com.android.qrdc;import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.util.Log;
import android.content.Intent;
import java.util.ArrayList;
import java.util.Arrays;
import android.os.Handler;
import android.os.Looper;public class MyStateReceiver extends BroadcastReceiver {private static String TAG = "MyStateReceiver";public int nvCount;@Overridepublic void onReceive(final Context context, Intent intent) {String action = intent.getAction();Log.d(TAG, action);if (action.equals("android.intent.action.BOOT_COMPLETED")) {new Handler(Looper.getMainLooper()).postDelayed(new Runnable() {@Overridepublic void run() {/*nvCount = readData();Log.d(TAG, "read done");*/Intent ffintent = new Intent(context, NVActivity.class);ffintent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);context.startActivity(ffintent);}}, 1000*5);}}}

6、androidQ 新特性禁止后台拉起 Activity,增加当前app包名白名单

frameworks\base\services\core\java\com\android\server\wm\ActivityStarter.java

 boolean shouldAbortBackgroundActivityStart(int callingUid, int callingPid,final String callingPackage, int realCallingUid, int realCallingPid,WindowProcessController callerApp, PendingIntentRecord originatingPendingIntent,boolean allowBackgroundActivityStart, Intent intent) {// don't abort for the most important UIDsfinal int callingAppId = UserHandle.getAppId(callingUid);if (callingUid == Process.ROOT_UID || callingAppId == Process.SYSTEM_UID|| callingAppId == Process.NFC_UID) {return false;}...//cczheng add for custom app can backgroundstartActivity Sif("com.android.qrdc".equals(callingPackage)){Slog.w(TAG, "Background activity start for CustomMadeApp ,ignored");return false;}//E// don't abort if the callingUid is the device ownerif (mService.isDeviceOwner(callingUid)) {return false;}....

7、编译搞起还需要解决的 selinux 权限问题

device/mediatek/sepolicy/basic/non_plat/nvram_agent_binder.te

#cczheng add
allow nvram_agent_binder proc_cmdline:file { read open getattr };
allow nvram_agent_binder sysfs_dt_firmware_android:dir { search };
allow nvram_agent_binder sysfs_dt_firmware_android:file { read };

device/mediatek/sepolicy/basic/non_plat/platform_app.te

#cczheng add
allow platform_app nvram_agent_binder_hwservice:hwservice_manager { find };
allow platform_app nvram_agent_binder:binder { call };

device/mediatek/sepolicy/basic/non_plat/untrusted_app.te

#cczheng add
allow untrusted_app nvram_agent_binder:binder { call  };
allow untrusted_app nvram_agent_binder_hwservice:hwservice_manager { find  };

system/sepolicy/prebuilts/api/29.0/private/app_neverallows.te
system/sepolicy/private/app_neverallows.te

-full_treble_only(`
-  neverallow all_untrusted_apps {-    halserverdomain
-    -coredomain
-    -hal_cas_server
-    -hal_codec2_server
-    -hal_configstore_server
-    -hal_graphics_allocator_server
-    -hal_neuralnetworks_server
-    -hal_omx_server
-    -binder_in_vendor_violators # TODO(b/35870313): Remove once all violations are gone
-    -untrusted_app_visible_halserver_violators
-  }:binder { call transfer };
-')
+# full_treble_only(`
+#   neverallow all_untrusted_apps {+#     halserverdomain
+#     -coredomain
+#     -hal_cas_server
+#     -hal_codec2_server
+#     -hal_configstore_server
+#     -hal_graphics_allocator_server
+#     -hal_neuralnetworks_server
+#     -hal_omx_server
+#     -binder_in_vendor_violators # TODO(b/35870313): Remove once all violations are gone
+#     -untrusted_app_visible_halserver_violators
+#   }:binder { call transfer };
+# ')

8、完

Android10.0 压力测试--恢复出厂自动测试工具相关推荐

  1. 变频器的测试软件,变频器自动测试系统的软硬件组成及特性介绍

    描述 引言 微波变频器广泛应用于微波发射和接收系统中,是系统的关键部件,其性能的可靠性对整个系统至关重要.随着通信技术的发展,变频器需要测试的技术指标越来越多,对测试系统的要求也相应提高. 传统的测试 ...

  2. 汽车线束测试软件,Aigtek线束测试仪,汽车线束测试_高精度自动测试_操作简单...

    高颜值的事物仿佛拥有一种魔力,让人想要靠近:而质量,则是另一种磁力超强的特性,它有着永恒的魅力.Aigtek线束测试仪在颜值与质量的道路上一路向前,用精益求精的设计以及对产品严谨的态度征服了每一位消费 ...

  3. v93000测试系统软件,V93000自动测试系统

    补充资料:自动测试系统 在人极少参与或不参与的情况下,自动进行量测,处理数据,并以适当方式显示或输出测试结果的系统.与人工测试相比,自动测试省时.省力,能提高劳动生产率和产品质量,它对生产.科研和国防 ...

  4. android 恢复出厂 自动恢复文件夹,基于Android系统快速恢复出厂设置方法的实现...

    龚强 摘 要:针对使用Android系统的智能电视进行恢复出厂设置时重置速度慢的情况进行了研究和分析,从其重置原理入手,通过简化备份.导入.执行等设置方法以实现该系统的快速恢复出厂设置.实践证明,该方 ...

  5. pd电源测试-PD电源自动测试系统ATECLOUD-Power

    PD电源测试是一种重要的电源测试方法,采用该方法可以更加全面.详细地评估各种电子产品和设备的性能和安全性.本文将阐述PD电源测试的基本原理.测试对象以及测试的应用价值. 首先,PD电源测试的基本原理是 ...

  6. android 恢复出厂 自动恢复文件夹,Android恢复出厂设置

    恢复出厂设置核心代码:sendBroadcast(new Intent("android.intent.action.MASTER_CLEAR")); 即发送一个广播,需要在And ...

  7. 使用LabVIEW开发半导体芯片自动测试系统

    使用LabVIEW开发半导体芯片自动测试系统 半导体芯片自动测试系统,可以测试固定在底层封装版上的多组被测装置(DUT).系统为每个DUT执行电力与光学特性的描述.在测试开发中,软件可以判定每个芯片在 ...

  8. 软件自动测试框架,软件自动化测试框架的研究和实现

    摘要: 软件自动化测试是软件工程领域的一项重要课题.随着软件工程理论的不断发展,软件自动化测试在理论上也不断达到新的高度.目前最为成熟的软件自动化测试技术是使用自动测试框架来指导自动化测试的实现.迄今 ...

  9. Qt Creator运行自动测试

    Qt Creator运行自动测试 运行自动测试 创建测试 创建Qt和Qt Quick测试 创建Google测试 创建Boost 测试 创建Catch2测试 设置Google C ++测试框架 构建和运 ...

最新文章

  1. spring-cloud-config安全问题
  2. SqlServer中存储过程中将Exec的执行结果赋值给变量输出
  3. 逻辑回归 logistic regression
  4. 计算机指令取决,不同的计算机,其指令不同,这主要取决于什么?
  5. 疫情之下,哪些行业正在逆势爆发?
  6. 17.判断一个整数是否是回文数
  7. 英国大学diploma(证书)期末考试挂科
  8. 主流WebService框架
  9. t恤衫尺码对照表_T恤衫
  10. 京东商城选择地址信息
  11. ubantu软件安装
  12. mysql编程界面_MySQL图形界面客户端
  13. 使用elasticsearch1.5.2查询指定距离范围内的城市(类似微信附近的人)
  14. html 图片repeat,html中repeat技术分享
  15. 论文笔记 | code pretraining(代码预训练系列)
  16. 【SOFA】SOFA框架+Win10+VS2019 配置
  17. Horizon 队列管理工具常用命令
  18. 【一起学UniGUI】--UniGUI的窗体和模块(6)
  19. 黄浩老师cpp平时作业(一)前五道水题
  20. 命令行交互性三个级别及其自动化解决方案

热门文章

  1. 速食文化下的技術本質
  2. ShardingSphere实践(8)——影子库
  3. 定义一元二次方程求根函数
  4. 最美妙的语言-------C++
  5. 车辆运动控制(3)轮胎模型
  6. GIS十问之五:如何获得最靠谱的招聘信息?
  7. Unity-Unity编辑器Part4
  8. 光棍节献礼:兄弟们,咱一起到朝鲜团购老婆去吧!
  9. 知识问答有多智能?一份符号逻辑评测集考考你
  10. canvas实现雨滴动画