本文共 7585 字,大约阅读时间需要 25 分钟。
方便连接logcat查看实时日志,正常情况下如果连接 USB 是无法进入doze模式,这个步骤是欺骗系统当前没有连接USB,虽然实际连接得好好的
adb shell dumpsys battery unplug
并不是每台机器都开启 alarm 的日志,所以我们可以命令强制开启
adb shell dumpsys alarm log on
要调试就进入深度休眠模式,即 deep idle mode
adb shell dumpsys deviceidle force-idle deep
starAlarmTaskByService(this, 5); public static void starAlarmTaskByService(Context context, int intervalMinute) { AlarmManager mAlarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE); long triggerAtMillis = System.currentTimeMillis() + (intervalMinute * 60 * 1000); Log.d(TAG, "starAlarmTaskByService action = " + ACTION_RTC_WAKEUP_ALRTM_TYPE_0_SERVIE + ", 下次唤醒时刻 = " + DateTimeUtil.getSysDate(triggerAtMillis)); Intent intent = new Intent(context, MyService.class); intent.setAction(ACTION_RTC_WAKEUP_ALRTM_TYPE_0_SERVIE); PendingIntent operation = PendingIntent.getService(context, 0, intent, PendingIntent.FLAG_CANCEL_CURRENT); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { mAlarmManager.setExact(AlarmManager.RTC_WAKEUP, triggerAtMillis, operation); } else { mAlarmManager.set(AlarmManager.RTC_WAKEUP, triggerAtMillis, operation); } }
注意这里的 flags
2018-08-23 14:25:07.989 934-24435/? V/AlarmManager: set(PendingIntent{c4c0513: PendingIntentRecord{ 59c2350 test.demo.alarm.zui.com.alarmtest startService}}) : type=0 triggerAtTime=1535005807985 win=0 tElapsed=70204635 maxElapsed=70204635 interval=0 flags=0x1(非DeviceIdleUserWhitelist白名单)
注意这里的 flags
2018-08-23 14:18:29.063 934-945/? V/AlarmManager: set(PendingIntent{c6e22ba: PendingIntentRecord{f55a56b test.demo.alarm.zui.com.alarmtest startService}}) : type=0 triggerAtTime=1535005409060 win=0 tElapsed=69805710 maxElapsed=69805710 interval=0 flags=0x9(DeviceIdleUserWhitelist白名单正常)
使用命令 adb shell dumpsys deviceidle whitelist 查看
这个是在系统源码路径 frameworks\base\data\etc\platform.xml,可以手机系统用 adb shell cat “/etc/permissions/platform.xml”查看
D:\AndroidStudioProjects>adb shell dumpsys deviceidle whitelistsystem-excidle,com.android.providers.downloads,10020system-excidle,com.android.shell,2000system,com.android.providers.downloads,10020system,com.android.shell,2000system,test.demo.alarm.zui.com.alarmtest,10090
这里是没有任何设置白名单
D:\AndroidStudioProjects>adb shell dumpsys deviceidle whitelistsystem-excidle,com.android.providers.downloads,10020system-excidle,com.android.shell,2000system,com.android.providers.downloads,10020system,com.android.shell,2000
这里是使用软件接口进行配置 mDeviceIdleService.addPowerSaveWhitelistApp(pkg);
D:\AndroidStudioProjects>adb shell dumpsys deviceidle whitelistsystem-excidle,com.android.providers.downloads,10020system-excidle,com.android.shell,2000system,com.android.providers.downloads,10020system,com.android.shell,2000user,test.demo.alarm.zui.com.alarmtest,10090
根据 mDeviceIdleUserWhitelist 进行对应的 flags 的重新设置,这个mDeviceIdleUserWhitelist是使用接口进行加入
private final IBinder mService = new IAlarmManager.Stub() { @Override public void set(String callingPackage, int type, long triggerAtTime, long windowLength, long interval, int flags, PendingIntent operation, IAlarmListener directReceiver, String listenerTag, WorkSource workSource, AlarmManager.AlarmClockInfo alarmClock) { ...省略 // If the caller is a core system component or on the user's whitelist, and not calling // to do work on behalf of someone else, then always set ALLOW_WHILE_IDLE_UNRESTRICTED. // This means we will allow these alarms to go off as normal even while idle, with no // timing restrictions. } else if (workSource == null && (callingUid < Process.FIRST_APPLICATION_UID || callingUid == mSystemUiUid || Arrays.binarySearch(mDeviceIdleUserWhitelist, UserHandle.getAppId(callingUid)) >= 0)) { flags |= AlarmManager.FLAG_ALLOW_WHILE_IDLE_UNRESTRICTED; flags &= ~AlarmManager.FLAG_ALLOW_WHILE_IDLE; } setImpl(type, triggerAtTime, windowLength, interval, operation, directReceiver, listenerTag, flags, workSource, alarmClock, callingUid, callingPackage); }
使用软件接口设置doze模式白名单,解决即可,这样就可以开心的准时接收消息了
/* * 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.sufadi.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 = "LavaPowerWhitelistBackend"; private static final String DEVICE_IDLE_SERVICE = "deviceidle"; private static final PowerWhitelistBackend INSTANCE = new PowerWhitelistBackend(); private final IDeviceIdleController mDeviceIdleService; private final ArraySetmWhitelistedApps = 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; }}
转载地址:http://kzjti.baihongyu.com/