上述备注规则如下
if(powerWhitelist.isSysWhitelisted(pkg)) {
// Summary of app which doesn't have a battery optimization setting
show:Battery optimization not available
} else {
if(powerWhitelist.isWhitelisted(pkg)) {
// Summary of app allowed to use a lot of power
show:Not optimized
} else {
// Summary of app which doesn't have a battery optimization setting
show:Optimizing battery use
}
}
package com.android.server;
/**
* Loads global system configuration info.
*/
public class SystemConfig {
static final String TAG = "SystemConfig";
SystemConfig() {
// Read configuration from system
readPermissions(Environment.buildPath(
Environment.getRootDirectory(), "etc", "sysconfig"), ALLOW_ALL);
// Read configuration from the old permissions dir
readPermissions(Environment.buildPath(
Environment.getRootDirectory(), "etc", "permissions"), ALLOW_ALL);
// Allow Vendor to customize system configs around libs, features, permissions and apps
int vendorPermissionFlag = ALLOW_LIBS | ALLOW_FEATURES | ALLOW_PERMISSIONS |
ALLOW_APP_CONFIGS;
readPermissions(Environment.buildPath(
Environment.getVendorDirectory(), "etc", "sysconfig"), vendorPermissionFlag);
readPermissions(Environment.buildPath(
Environment.getVendorDirectory(), "etc", "permissions"), vendorPermissionFlag);
// Allow ODM to customize system configs around libs, features and apps
int odmPermissionFlag = ALLOW_LIBS | ALLOW_FEATURES | ALLOW_APP_CONFIGS;
readPermissions(Environment.buildPath(
Environment.getOdmDirectory(), "etc", "sysconfig"), odmPermissionFlag);
readPermissions(Environment.buildPath(
Environment.getOdmDirectory(), "etc", "permissions"), odmPermissionFlag);
// Only allow OEM to customize features
readPermissions(Environment.buildPath(
Environment.getOemDirectory(), "etc", "sysconfig"), ALLOW_FEATURES);
readPermissions(Environment.buildPath(
Environment.getOemDirectory(), "etc", "permissions"), ALLOW_FEATURES);
}
由于Android O 解耦的思想,上述源码即如下路径
1.RootDirectory
etc/sysconfig/
etc/permissions/
我的机器没有etc/sysconfig/路径
Z50:/etc/permissions # ls
ls
android.software.live_wallpaper.xml mediatek-packages-teleservice.xml
android.software.webview.xml platform.xml
com.android.location.provider.xml pms_sysapp_removable_system_list.txt
com.android.media.remotedisplay.xml privapp-permissions-google.xml
com.android.mediadrm.signer.xml privapp-permissions-mediatek.xml
com.google.android.maps.xml privapp-permissions-platform.xml
com.google.android.media.effects.xml
2.VendorDirectory
vendor/etc/sysconfig/
vendor/etc/permissions/
我的机器没有vendor/etc/sysconfig/路径
Z50:/vendor/etc/permissions # ls
ls
android.hardware.audio.low_latency.xml
android.hardware.bluetooth.xml
android.hardware.bluetooth_le.xml
android.hardware.camera.xml
android.hardware.faketouch.xml
android.hardware.location.gps.xml
android.hardware.microphone.xml
android.hardware.sensor.accelerometer.xml
android.hardware.sensor.light.xml
android.hardware.sensor.proximity.xml
android.hardware.telephony.gsm.xml
android.hardware.touchscreen.multitouch.distinct.xml
android.hardware.touchscreen.multitouch.jazzhand.xml
android.hardware.touchscreen.multitouch.xml
android.hardware.touchscreen.xml
android.hardware.usb.accessory.xml
android.hardware.usb.host.xml
android.hardware.wifi.direct.xml
android.hardware.wifi.xml
android.software.live_wallpaper.xml
android.software.midi.xml
handheld_core_hardware.xml
pms_sysapp_removable_vendor_list.txt
3.OdmDirectory
odm/etc/sysconfig/
odm/etc/permissions/
很可惜,都没有,这里主要给ODM自己建立对应文件夹进行配置
2|Z50:/ # ls
ls
acct data init.preload.rc nvdata sdcard
bugreports default.prop init.rc oem storage
cache dev init.usb.configfs.rc proc sys
charger etc init.usb.rc protect_f system
config fstab.enableswap init.zygote32.rc protect_s ueventd.rc
custom init mnt root vendor
d init.environ.rc nvcfg sbin
3.oemDirectory
oem/etc/sysconfig/
oem/etc/permissions/
没有具体文件
Z50:/oem # ls
ls
具体源码
void readPermissions(File libraryDir, int permissionFlag) {
// Read permissions from given directory.
if (!libraryDir.exists() || !libraryDir.isDirectory()) {
if (permissionFlag == ALLOW_ALL) {
Slog.w(TAG, "No directory " + libraryDir + ", skipping");
}
return;
}
if (!libraryDir.canRead()) {
Slog.w(TAG, "Directory " + libraryDir + " cannot be read");
return;
}
// Iterate over the files in the directory and scan .xml files
File platformFile = null;
for (File f : libraryDir.listFiles()) {
// We'll read platform.xml last
// 这个文件最后会读的
if (f.getPath().endsWith("etc/permissions/platform.xml")) {
platformFile = f;
continue;
}
if (!f.getPath().endsWith(".xml")) {
Slog.i(TAG, "Non-xml file " + f + " in " + libraryDir + " directory, ignoring");
continue;
}
if (!f.canRead()) {
Slog.w(TAG, "Permissions library file " + f + " cannot be read");
continue;
}
readPermissionsFromXml(f, permissionFlag);
}
// Read platform permissions last so it will take precedence
// 我就是最后
if (platformFile != null) {
readPermissionsFromXml(platformFile, permissionFlag);
}
}
接下来很明显就是读取各种XML了
private void readPermissionsFromXml(File permFile, int permissionFlag) {
我们重点关注下面的即可
...
} else if ("allow-in-power-save-except-idle".equals(name) && allowAll) {
String pkgname = parser.getAttributeValue(null, "package");
if (pkgname == null) {
Slog.w(TAG, " without package in "
+ permFile + " at " + parser.getPositionDescription());
} else {
mAllowInPowerSaveExceptIdle.add(pkgname);
}
XmlUtils.skipCurrentTag(parser);
continue;
} else if ("allow-in-power-save".equals(name) && allowAll) {
String pkgname = parser.getAttributeValue(null, "package");
if (pkgname == null) {
Slog.w(TAG, " without package in " + permFile + " at "
+ parser.getPositionDescription());
} else {
mAllowInPowerSave.add(pkgname);
}
XmlUtils.skipCurrentTag(parser);
continue;
...
对应源代码路径如下
<allow-in-power-save package="com.android.providers.downloads" />
<allow-in-power-save package="com.android.cellbroadcastreceiver" />
<allow-in-power-save package="com.android.shell" />
当然内容是一样的啦
<allow-in-power-save package="com.android.providers.downloads" />
<allow-in-power-save package="com.android.cellbroadcastreceiver" />
<allow-in-power-save package="com.android.shell" />
这里是亲爱的Gms包设置
Line 23: <allow-in-power-save package="com.google.android.gms" />
Line 28: <allow-in-power-save-except-idle package="com.google.android.apps.work.oobconfig" />
Line 41: <allow-in-power-save-except-idle package="com.android.vending" />
Line 44: <allow-in-power-save package="com.google.android.volta" />
Line 48: <allow-in-power-save package="com.google.android.ims" />
// Doze 模式新增白名单
public void addApp(String pkg) {
try {
mDeviceIdleService.addPowerSaveWhitelistApp(pkg);
mWhitelistedApps.add(pkg);
} catch (RemoteException e) {
Log.w(TAG, "Unable to reach IDeviceIdleController", e);
}
}
// Doze 模式移除白名单
public void removeApp(String pkg) {
try {
mDeviceIdleService.removePowerSaveWhitelistApp(pkg);
mWhitelistedApps.remove(pkg);
} catch (RemoteException e) {
Log.w(TAG, "Unable to reach IDeviceIdleController", e);
}
}
具体工具类如下
/*
* Copyright (C) 2015 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.lava.powersave.util;
import android.os.IDeviceIdleController;
import android.os.RemoteException;
import android.os.ServiceManager;
import android.util.ArraySet;
import android.util.Log;
/**
* Handles getting/changing the whitelist for the exceptions to battery saving features.
*/
public class PowerWhitelistBackend {
private static final String TAG = "WhitelistBackend";
private static final String DEVICE_IDLE_SERVICE = "deviceidle";
private static final PowerWhitelistBackend INSTANCE = new PowerWhitelistBackend();
private final IDeviceIdleController mDeviceIdleService;
private final ArraySet mWhitelistedApps = new ArraySet<>();
private final ArraySet mSysWhitelistedApps = new ArraySet<>();
public PowerWhitelistBackend() {
mDeviceIdleService = IDeviceIdleController.Stub.asInterface(
ServiceManager.getService(DEVICE_IDLE_SERVICE));
refreshList();
}
public int getWhitelistSize() {
return mWhitelistedApps.size();
}
public boolean isSysWhitelisted(String pkg) {
return mSysWhitelistedApps.contains(pkg);
}
public boolean isWhitelisted(String pkg) {
return mWhitelistedApps.contains(pkg);
}
public void addApp(String pkg) {
try {
mDeviceIdleService.addPowerSaveWhitelistApp(pkg);
mWhitelistedApps.add(pkg);
} catch (RemoteException e) {
Log.w(TAG, "Unable to reach IDeviceIdleController", e);
}
}
public void removeApp(String pkg) {
try {
mDeviceIdleService.removePowerSaveWhitelistApp(pkg);
mWhitelistedApps.remove(pkg);
} catch (RemoteException e) {
Log.w(TAG, "Unable to reach IDeviceIdleController", e);
}
}
private void refreshList() {
mSysWhitelistedApps.clear();
mWhitelistedApps.clear();
try {
String[] whitelistedApps = mDeviceIdleService.getFullPowerWhitelist();
for (String app : whitelistedApps) {
mWhitelistedApps.add(app);
}
String[] sysWhitelistedApps = mDeviceIdleService.getSystemPowerWhitelist();
for (String app : sysWhitelistedApps) {
mSysWhitelistedApps.add(app);
}
} catch (RemoteException e) {
Log.w(TAG, "Unable to reach IDeviceIdleController", e);
}
}
public static PowerWhitelistBackend getInstance() {
return INSTANCE;
}
}
软件接口的配置也会体现这这个路径下
data/system/deviceidle.xml
Z50:/data/system # cat deviceidle.xml
cat deviceidle.xml
<config>
<wl n="com.google.android.apps.maps" />
<wl n="com.google.android.gsf" />
config>
具体相关源码
public final AtomicFile mConfigFile;
public DeviceIdleController(Context context) {
super(context);
mConfigFile = new AtomicFile(new File(getSystemDir(), "deviceidle.xml"));
mHandler = new MyHandler(BackgroundThread.getHandler().getLooper());
}
Doze模式的白名单我们可以预设置还可以进行软件接口调用。
1.主要预设置在
frameworks\base\data\etc\platform.xml
随着Android O 的代码控制雄心,以后路径可能需要厂商自己定义
vendor\mediatek\proprietary\frameworks\base\data\etc\platform.xml
2.不要忘记GMS包里面也可以配置的
\vendor\partner_gms\etc\sysconfig\google.xml
3.接口调用同样Google提供给我们了,使用起来同样简单粗暴,查看设置结果 data/system/deviceidle.xml
上述备注规则如下
if(powerWhitelist.isSysWhitelisted(pkg)) {
// Summary of app which doesn't have a battery optimization setting
show:Battery optimization not available
} else {
if(powerWhitelist.isWhitelisted(pkg)) {
// Summary of app allowed to use a lot of power
show:Not optimized
} else {
// Summary of app which doesn't have a battery optimization setting
show:Optimizing battery use
}
}
package com.android.server;
/**
* Loads global system configuration info.
*/
public class SystemConfig {
static final String TAG = "SystemConfig";
SystemConfig() {
// Read configuration from system
readPermissions(Environment.buildPath(
Environment.getRootDirectory(), "etc", "sysconfig"), ALLOW_ALL);
// Read configuration from the old permissions dir
readPermissions(Environment.buildPath(
Environment.getRootDirectory(), "etc", "permissions"), ALLOW_ALL);
// Allow Vendor to customize system configs around libs, features, permissions and apps
int vendorPermissionFlag = ALLOW_LIBS | ALLOW_FEATURES | ALLOW_PERMISSIONS |
ALLOW_APP_CONFIGS;
readPermissions(Environment.buildPath(
Environment.getVendorDirectory(), "etc", "sysconfig"), vendorPermissionFlag);
readPermissions(Environment.buildPath(
Environment.getVendorDirectory(), "etc", "permissions"), vendorPermissionFlag);
// Allow ODM to customize system configs around libs, features and apps
int odmPermissionFlag = ALLOW_LIBS | ALLOW_FEATURES | ALLOW_APP_CONFIGS;
readPermissions(Environment.buildPath(
Environment.getOdmDirectory(), "etc", "sysconfig"), odmPermissionFlag);
readPermissions(Environment.buildPath(
Environment.getOdmDirectory(), "etc", "permissions"), odmPermissionFlag);
// Only allow OEM to customize features
readPermissions(Environment.buildPath(
Environment.getOemDirectory(), "etc", "sysconfig"), ALLOW_FEATURES);
readPermissions(Environment.buildPath(
Environment.getOemDirectory(), "etc", "permissions"), ALLOW_FEATURES);
}
由于Android O 解耦的思想,上述源码即如下路径
1.RootDirectory
etc/sysconfig/
etc/permissions/
我的机器没有etc/sysconfig/路径
Z50:/etc/permissions # ls
ls
android.software.live_wallpaper.xml mediatek-packages-teleservice.xml
android.software.webview.xml platform.xml
com.android.location.provider.xml pms_sysapp_removable_system_list.txt
com.android.media.remotedisplay.xml privapp-permissions-google.xml
com.android.mediadrm.signer.xml privapp-permissions-mediatek.xml
com.google.android.maps.xml privapp-permissions-platform.xml
com.google.android.media.effects.xml
2.VendorDirectory
vendor/etc/sysconfig/
vendor/etc/permissions/
我的机器没有vendor/etc/sysconfig/路径
Z50:/vendor/etc/permissions # ls
ls
android.hardware.audio.low_latency.xml
android.hardware.bluetooth.xml
android.hardware.bluetooth_le.xml
android.hardware.camera.xml
android.hardware.faketouch.xml
android.hardware.location.gps.xml
android.hardware.microphone.xml
android.hardware.sensor.accelerometer.xml
android.hardware.sensor.light.xml
android.hardware.sensor.proximity.xml
android.hardware.telephony.gsm.xml
android.hardware.touchscreen.multitouch.distinct.xml
android.hardware.touchscreen.multitouch.jazzhand.xml
android.hardware.touchscreen.multitouch.xml
android.hardware.touchscreen.xml
android.hardware.usb.accessory.xml
android.hardware.usb.host.xml
android.hardware.wifi.direct.xml
android.hardware.wifi.xml
android.software.live_wallpaper.xml
android.software.midi.xml
handheld_core_hardware.xml
pms_sysapp_removable_vendor_list.txt
3.OdmDirectory
odm/etc/sysconfig/
odm/etc/permissions/
很可惜,都没有,这里主要给ODM自己建立对应文件夹进行配置
2|Z50:/ # ls
ls
acct data init.preload.rc nvdata sdcard
bugreports default.prop init.rc oem storage
cache dev init.usb.configfs.rc proc sys
charger etc init.usb.rc protect_f system
config fstab.enableswap init.zygote32.rc protect_s ueventd.rc
custom init mnt root vendor
d init.environ.rc nvcfg sbin
3.oemDirectory
oem/etc/sysconfig/
oem/etc/permissions/
没有具体文件
Z50:/oem # ls
ls
具体源码
void readPermissions(File libraryDir, int permissionFlag) {
// Read permissions from given directory.
if (!libraryDir.exists() || !libraryDir.isDirectory()) {
if (permissionFlag == ALLOW_ALL) {
Slog.w(TAG, "No directory " + libraryDir + ", skipping");
}
return;
}
if (!libraryDir.canRead()) {
Slog.w(TAG, "Directory " + libraryDir + " cannot be read");
return;
}
// Iterate over the files in the directory and scan .xml files
File platformFile = null;
for (File f : libraryDir.listFiles()) {
// We'll read platform.xml last
// 这个文件最后会读的
if (f.getPath().endsWith("etc/permissions/platform.xml")) {
platformFile = f;
continue;
}
if (!f.getPath().endsWith(".xml")) {
Slog.i(TAG, "Non-xml file " + f + " in " + libraryDir + " directory, ignoring");
continue;
}
if (!f.canRead()) {
Slog.w(TAG, "Permissions library file " + f + " cannot be read");
continue;
}
readPermissionsFromXml(f, permissionFlag);
}
// Read platform permissions last so it will take precedence
// 我就是最后
if (platformFile != null) {
readPermissionsFromXml(platformFile, permissionFlag);
}
}
接下来很明显就是读取各种XML了
private void readPermissionsFromXml(File permFile, int permissionFlag) {
我们重点关注下面的即可
...
} else if ("allow-in-power-save-except-idle".equals(name) && allowAll) {
String pkgname = parser.getAttributeValue(null, "package");
if (pkgname == null) {
Slog.w(TAG, " without package in "
+ permFile + " at " + parser.getPositionDescription());
} else {
mAllowInPowerSaveExceptIdle.add(pkgname);
}
XmlUtils.skipCurrentTag(parser);
continue;
} else if ("allow-in-power-save".equals(name) && allowAll) {
String pkgname = parser.getAttributeValue(null, "package");
if (pkgname == null) {
Slog.w(TAG, " without package in " + permFile + " at "
+ parser.getPositionDescription());
} else {
mAllowInPowerSave.add(pkgname);
}
XmlUtils.skipCurrentTag(parser);
continue;
...
对应源代码路径如下
<allow-in-power-save package="com.android.providers.downloads" />
<allow-in-power-save package="com.android.cellbroadcastreceiver" />
<allow-in-power-save package="com.android.shell" />
当然内容是一样的啦
<allow-in-power-save package="com.android.providers.downloads" />
<allow-in-power-save package="com.android.cellbroadcastreceiver" />
<allow-in-power-save package="com.android.shell" />
这里是亲爱的Gms包设置
Line 23: <allow-in-power-save package="com.google.android.gms" />
Line 28: <allow-in-power-save-except-idle package="com.google.android.apps.work.oobconfig" />
Line 41: <allow-in-power-save-except-idle package="com.android.vending" />
Line 44: <allow-in-power-save package="com.google.android.volta" />
Line 48: <allow-in-power-save package="com.google.android.ims" />
// Doze 模式新增白名单
public void addApp(String pkg) {
try {
mDeviceIdleService.addPowerSaveWhitelistApp(pkg);
mWhitelistedApps.add(pkg);
} catch (RemoteException e) {
Log.w(TAG, "Unable to reach IDeviceIdleController", e);
}
}
// Doze 模式移除白名单
public void removeApp(String pkg) {
try {
mDeviceIdleService.removePowerSaveWhitelistApp(pkg);
mWhitelistedApps.remove(pkg);
} catch (RemoteException e) {
Log.w(TAG, "Unable to reach IDeviceIdleController", e);
}
}
具体工具类如下
/*
* Copyright (C) 2015 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.lava.powersave.util;
import android.os.IDeviceIdleController;
import android.os.RemoteException;
import android.os.ServiceManager;
import android.util.ArraySet;
import android.util.Log;
/**
* Handles getting/changing the whitelist for the exceptions to battery saving features.
*/
public class PowerWhitelistBackend {
private static final String TAG = "WhitelistBackend";
private static final String DEVICE_IDLE_SERVICE = "deviceidle";
private static final PowerWhitelistBackend INSTANCE = new PowerWhitelistBackend();
private final IDeviceIdleController mDeviceIdleService;
private final ArraySet mWhitelistedApps = new ArraySet<>();
private final ArraySet mSysWhitelistedApps = new ArraySet<>();
public PowerWhitelistBackend() {
mDeviceIdleService = IDeviceIdleController.Stub.asInterface(
ServiceManager.getService(DEVICE_IDLE_SERVICE));
refreshList();
}
public int getWhitelistSize() {
return mWhitelistedApps.size();
}
public boolean isSysWhitelisted(String pkg) {
return mSysWhitelistedApps.contains(pkg);
}
public boolean isWhitelisted(String pkg) {
return mWhitelistedApps.contains(pkg);
}
public void addApp(String pkg) {
try {
mDeviceIdleService.addPowerSaveWhitelistApp(pkg);
mWhitelistedApps.add(pkg);
} catch (RemoteException e) {
Log.w(TAG, "Unable to reach IDeviceIdleController", e);
}
}
public void removeApp(String pkg) {
try {
mDeviceIdleService.removePowerSaveWhitelistApp(pkg);
mWhitelistedApps.remove(pkg);
} catch (RemoteException e) {
Log.w(TAG, "Unable to reach IDeviceIdleController", e);
}
}
private void refreshList() {
mSysWhitelistedApps.clear();
mWhitelistedApps.clear();
try {
String[] whitelistedApps = mDeviceIdleService.getFullPowerWhitelist();
for (String app : whitelistedApps) {
mWhitelistedApps.add(app);
}
String[] sysWhitelistedApps = mDeviceIdleService.getSystemPowerWhitelist();
for (String app : sysWhitelistedApps) {
mSysWhitelistedApps.add(app);
}
} catch (RemoteException e) {
Log.w(TAG, "Unable to reach IDeviceIdleController", e);
}
}
public static PowerWhitelistBackend getInstance() {
return INSTANCE;
}
}
软件接口的配置也会体现这这个路径下
data/system/deviceidle.xml
Z50:/data/system # cat deviceidle.xml
cat deviceidle.xml
<config>
<wl n="com.google.android.apps.maps" />
<wl n="com.google.android.gsf" />
config>
具体相关源码
public final AtomicFile mConfigFile;
public DeviceIdleController(Context context) {
super(context);
mConfigFile = new AtomicFile(new File(getSystemDir(), "deviceidle.xml"));
mHandler = new MyHandler(BackgroundThread.getHandler().getLooper());
}
Doze模式的白名单我们可以预设置还可以进行软件接口调用。
1.主要预设置在
frameworks\base\data\etc\platform.xml
随着Android O 的代码控制雄心,以后路径可能需要厂商自己定义
vendor\mediatek\proprietary\frameworks\base\data\etc\platform.xml
2.不要忘记GMS包里面也可以配置的
\vendor\partner_gms\etc\sysconfig\google.xml
3.接口调用同样Google提供给我们了,使用起来同样简单粗暴,查看设置结果 data/system/deviceidle.xml