天天看點

Android O 的Doze模式白名單路徑Doze 模式清單具體讀取路徑源碼如下軟體接口設定總結

Doze 模式清單

Android O 的Doze模式白名單路徑Doze 模式清單具體讀取路徑源碼如下軟體接口設定總結

上述備注規則如下

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自己建立對應檔案夾進行配置
|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, "<allow-in-power-save-except-idle> 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, "<allow-in-power-save> without package in " + permFile + " at "
                                + parser.getPositionDescription());
                    } else {
                        mAllowInPowerSave.add(pkgname);
                    }
                    XmlUtils.skipCurrentTag(parser);
                    continue;
...                    
           

取出白名單

手機路徑 /etc/permissions/platform.xml

對應源代碼路徑如下

<!-- These are the standard packages that are white-listed to always have internet
         access while in power save mode, even if they aren't in the foreground. -->
    <allow-in-power-save package="com.android.providers.downloads" />

    <!-- This is a core platform component that needs to freely run in the background -->
    <allow-in-power-save package="com.android.cellbroadcastreceiver" />
    <allow-in-power-save package="com.android.shell" />
           

系統源碼路徑 frameworks\base\data\etc\platform.xml

當然内容是一樣的啦
    <!-- These are the standard packages that are white-listed to always have internet
         access while in power save mode, even if they aren't in the foreground. -->
    <allow-in-power-save package="com.android.providers.downloads" />

    <!-- This is a core platform component that needs to freely run in the background -->
    <allow-in-power-save package="com.android.cellbroadcastreceiver" />
    <allow-in-power-save package="com.android.shell" />
           

手機路徑 /vendor/etc/permissions/抱歉這裡沒有

系統源碼路徑 vendor\mediatek\proprietary\frameworks\base\data\etc\抱歉這裡也沒有,需要自行配置

系統源碼路徑 \vendor\partner_gms\etc\sysconfig\google.xml

這裡是親愛的Gms包設定
    Line :     <allow-in-power-save package="com.google.android.gms" />
    Line :     <allow-in-power-save-except-idle package="com.google.android.apps.work.oobconfig" />
    Line :     <allow-in-power-save-except-idle package="com.android.vending" />
    Line :     <allow-in-power-save package="com.google.android.volta" />
    Line :     <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<String> mWhitelistedApps = new ArraySet<>();
    private final ArraySet<String> 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
<?xml version='1.0' encoding='utf-8' standalone='yes' ?>
<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