这里以MTK6765 Android S举例说明,Android系统在加载客户应用白名单的过程。
首先Android系统可以根据不同手机厂商的需要进行源码的定制,当然定制应用白名单也是可以的,一般情况下在Android源码目录下存在一个Vendor文件夹,该文件夹是Android专门为不同手机厂商定制使用的文件夹,我们可以在里面做一些定制的操作。
一般情况下不同的项目对于白名单的需要是不一样的,所有这里只针对我们公司的某个项目而言其白名单的所在路径是/vendor/xxxxx/product/common_req/xxxx/etc/deviceidle.xml,其内容如图,好了现在我们知道了这个xml里的配置是什么样的了,问题了接下来我们要怎么在系统中去解析这个xml文件哩?
一般情况下我们在编译Android源码的时候是使用脚本命令去编译的,这里我展示我们公司脚本命令的一部分,就是通过PRODUCT_COPY_FILES将/vendor/xxxxx/product/common_req/xxxx/etc/deviceidle.xml的配置文件copy到手机的system/etc文件夹下为接下来framework层的解析做好准备。
好了之前做了做了这么多的事情终于要到解析的环节了,在Android S解析白名单与之前有一些不同,Android S 使用DeviceIdleController.java中来解析/deviceidle.xml的配置(这个类在 /frameworks/base/apex/jobscheduler/service/java/com/android/server/DeviceIdleController.java),可以看到DeviceIdleController是通过一个BroadcastReceiver来接收解析deviceidle,case Intent.ACTION_PACKAGE_ADDED为我司根据需求解析白名单的逻辑,在收到ACTION_PACKAGE_ADDED的广播之后,通过AtomicFile mConfigFileForJourney = new AtomicFile(new File(getSystemETCDir(), "deviceidle.xml"))将deviceidle.xml读取出来转换成一个AtomicFile,在通过readDefaultConfigFileLocked去解析deviceidle的格式,那么具体是怎么解析的尼?
private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
@Override public void onReceive(Context context, Intent intent) {
switch (intent.getAction()) {
case ConnectivityManager.CONNECTIVITY_ACTION: {
updateConnectivityState(intent);
} break;
case Intent.ACTION_BATTERY_CHANGED: {
boolean present = intent.getBooleanExtra(BatteryManager.EXTRA_PRESENT, true);
boolean plugged = intent.getIntExtra(BatteryManager.EXTRA_PLUGGED, 0) != 0;
synchronized (DeviceIdleController.this) {
updateChargingLocked(present && plugged);
}
} break;
case Intent.ACTION_PACKAGE_REMOVED: {
if (!intent.getBooleanExtra(Intent.EXTRA_REPLACING, false)) {
Uri data = intent.getData();
String ssp;
if (data != null && (ssp = data.getSchemeSpecificPart()) != null) {
removePowerSaveWhitelistAppInternal(ssp);
}
}
} break;
case Intent.ACTION_PACKAGE_ADDED: {
Slog.d(TAG, "Intent.ACTION_PACKAGE_ADDED received");
if (JourneyCustomFeature.DEVICEIDLE_WHITELIST_SUPPORT && !intent.getBooleanExtra(Intent.EXTRA_REPLACING, false)) {
//先读取一次配置文件
readConfigFileLocked();
AtomicFile mConfigFileForCustomer = new AtomicFile(new File(getSystemETCDir(), "deviceidle_customer.xml"));
AtomicFile mConfigFileForJourney = new AtomicFile(new File(getSystemETCDir(), "deviceidle.xml"));
//根据需要去读取相应的配置文件
readDefaultConfigFileLocked(mConfigFileForCustomer);
r