diff options
11 files changed, 227 insertions, 64 deletions
diff --git a/core/java/android/app/ContextImpl.java b/core/java/android/app/ContextImpl.java index c07140c..235f294 100644 --- a/core/java/android/app/ContextImpl.java +++ b/core/java/android/app/ContextImpl.java @@ -960,14 +960,21 @@ class ContextImpl extends Context { String receiverPermission, BroadcastReceiver resultReceiver, Handler scheduler, int initialCode, String initialData, Bundle initialExtras) { sendOrderedBroadcastAsUser(intent, user, receiverPermission, AppOpsManager.OP_NONE, - resultReceiver, scheduler, initialCode, initialData, initialExtras); + null, resultReceiver, scheduler, initialCode, initialData, initialExtras); } @Override public void sendOrderedBroadcastAsUser(Intent intent, UserHandle user, String receiverPermission, int appOp, BroadcastReceiver resultReceiver, - Handler scheduler, - int initialCode, String initialData, Bundle initialExtras) { + Handler scheduler, int initialCode, String initialData, Bundle initialExtras) { + sendOrderedBroadcastAsUser(intent, user, receiverPermission, appOp, + null, resultReceiver, scheduler, initialCode, initialData, initialExtras); + } + + @Override + public void sendOrderedBroadcastAsUser(Intent intent, UserHandle user, + String receiverPermission, int appOp, Bundle options, BroadcastReceiver resultReceiver, + Handler scheduler, int initialCode, String initialData, Bundle initialExtras) { IIntentReceiver rd = null; if (resultReceiver != null) { if (mPackageInfo != null) { @@ -981,8 +988,8 @@ class ContextImpl extends Context { if (scheduler == null) { scheduler = mMainThread.getHandler(); } - rd = new LoadedApk.ReceiverDispatcher( - resultReceiver, getOuterContext(), scheduler, null, false).getIIntentReceiver(); + rd = new LoadedApk.ReceiverDispatcher(resultReceiver, getOuterContext(), + scheduler, null, false).getIIntentReceiver(); } } String resolvedType = intent.resolveTypeIfNeeded(getContentResolver()); @@ -993,7 +1000,7 @@ class ContextImpl extends Context { ActivityManagerNative.getDefault().broadcastIntent( mMainThread.getApplicationThread(), intent, resolvedType, rd, initialCode, initialData, initialExtras, receiverPermissions, - appOp, null, true, false, user.getIdentifier()); + appOp, options, true, false, user.getIdentifier()); } catch (RemoteException e) { throw new RuntimeException("Failure from system", e); } diff --git a/core/java/android/content/Context.java b/core/java/android/content/Context.java index 0bfe108..4c7dd10 100644 --- a/core/java/android/content/Context.java +++ b/core/java/android/content/Context.java @@ -1809,6 +1809,17 @@ public abstract class Context { @Nullable Bundle initialExtras); /** + * Similar to above but takes an appOp as well, to enforce restrictions, and an options Bundle. + * @see #sendOrderedBroadcastAsUser(Intent, UserHandle, String, + * BroadcastReceiver, Handler, int, String, Bundle) + * @hide + */ + public abstract void sendOrderedBroadcastAsUser(Intent intent, UserHandle user, + @Nullable String receiverPermission, int appOp, @Nullable Bundle options, + BroadcastReceiver resultReceiver, @Nullable Handler scheduler, int initialCode, + @Nullable String initialData, @Nullable Bundle initialExtras); + + /** * <p>Perform a {@link #sendBroadcast(Intent)} that is "sticky," meaning the * Intent you are sending stays around after the broadcast is complete, * so that others can quickly retrieve that data through the return diff --git a/core/java/android/content/ContextWrapper.java b/core/java/android/content/ContextWrapper.java index 8ad3d21..8359edf 100644 --- a/core/java/android/content/ContextWrapper.java +++ b/core/java/android/content/ContextWrapper.java @@ -489,12 +489,20 @@ public class ContextWrapper extends Context { @Override public void sendOrderedBroadcastAsUser(Intent intent, UserHandle user, String receiverPermission, int appOp, BroadcastReceiver resultReceiver, - Handler scheduler, - int initialCode, String initialData, Bundle initialExtras) { + Handler scheduler, int initialCode, String initialData, Bundle initialExtras) { mBase.sendOrderedBroadcastAsUser(intent, user, receiverPermission, appOp, resultReceiver, scheduler, initialCode, initialData, initialExtras); } + /** @hide */ + @Override + public void sendOrderedBroadcastAsUser(Intent intent, UserHandle user, + String receiverPermission, int appOp, Bundle options, BroadcastReceiver resultReceiver, + Handler scheduler, int initialCode, String initialData, Bundle initialExtras) { + mBase.sendOrderedBroadcastAsUser(intent, user, receiverPermission, appOp, options, + resultReceiver, scheduler, initialCode, initialData, initialExtras); + } + @Override @Deprecated public void sendStickyBroadcast(Intent intent) { diff --git a/core/java/android/os/BatteryStats.java b/core/java/android/os/BatteryStats.java index adc84bc..452e4d5 100644 --- a/core/java/android/os/BatteryStats.java +++ b/core/java/android/os/BatteryStats.java @@ -1193,9 +1193,11 @@ public abstract class BatteryStats implements Parcelable { public static final int EVENT_PACKAGE_INACTIVE = 0x000f; // Event for a package becoming active due to an interaction. public static final int EVENT_PACKAGE_ACTIVE = 0x0010; + // Event for a package being on the temporary whitelist. + public static final int EVENT_TEMP_WHITELIST = 0x0011; // Number of event types. - public static final int EVENT_COUNT = 0x0011; + public static final int EVENT_COUNT = 0x0012; // Mask to extract out only the type part of the event. public static final int EVENT_TYPE_MASK = ~(EVENT_FLAG_START|EVENT_FLAG_FINISH); @@ -1219,6 +1221,10 @@ public abstract class BatteryStats implements Parcelable { EVENT_USER_FOREGROUND | EVENT_FLAG_FINISH; public static final int EVENT_ALARM_START = EVENT_ALARM | EVENT_FLAG_START; public static final int EVENT_ALARM_FINISH = EVENT_ALARM | EVENT_FLAG_FINISH; + public static final int EVENT_TEMP_WHITELIST_START = + EVENT_TEMP_WHITELIST | EVENT_FLAG_START; + public static final int EVENT_TEMP_WHITELIST_FINISH = + EVENT_TEMP_WHITELIST | EVENT_FLAG_FINISH; // For CMD_EVENT. public int eventCode; @@ -1852,12 +1858,12 @@ public abstract class BatteryStats implements Parcelable { public static final String[] HISTORY_EVENT_NAMES = new String[] { "null", "proc", "fg", "top", "sync", "wake_lock_in", "job", "user", "userfg", "conn", - "active", "pkginst", "pkgunin", "alarm", "stats", "inactive", "active" + "active", "pkginst", "pkgunin", "alarm", "stats", "inactive", "active", "tmpwhitelist" }; public static final String[] HISTORY_EVENT_CHECKIN_NAMES = new String[] { "Enl", "Epr", "Efg", "Etp", "Esy", "Ewl", "Ejb", "Eur", "Euf", "Ecn", - "Eac", "Epi", "Epu", "Eal", "Est", "Eai", "Eaa" + "Eac", "Epi", "Epu", "Eal", "Est", "Eai", "Eaa", "Etw" }; /** diff --git a/core/java/android/os/IDeviceIdleController.aidl b/core/java/android/os/IDeviceIdleController.aidl index fe4aa13..b768852 100644 --- a/core/java/android/os/IDeviceIdleController.aidl +++ b/core/java/android/os/IDeviceIdleController.aidl @@ -27,6 +27,7 @@ interface IDeviceIdleController { int[] getAppIdWhitelist(); int[] getAppIdTempWhitelist(); boolean isPowerSaveWhitelistApp(String name); - void addPowerSaveTempWhitelistApp(String name, long duration, int userId); + void addPowerSaveTempWhitelistApp(String name, long duration, int userId, String reason); + long addPowerSaveTempWhitelistAppForMms(String name, int userId, String reason); void exitIdle(String reason); } diff --git a/services/core/java/com/android/server/DeviceIdleController.java b/services/core/java/com/android/server/DeviceIdleController.java index fde1490..08b2332 100644 --- a/services/core/java/com/android/server/DeviceIdleController.java +++ b/services/core/java/com/android/server/DeviceIdleController.java @@ -36,6 +36,7 @@ import android.hardware.TriggerEventListener; import android.hardware.display.DisplayManager; import android.net.INetworkPolicyManager; import android.net.Uri; +import android.os.BatteryStats; import android.os.Binder; import android.os.Environment; import android.os.FileUtils; @@ -54,9 +55,11 @@ import android.provider.Settings; import android.util.ArrayMap; import android.util.ArraySet; import android.util.KeyValueListParser; +import android.util.MutableLong; +import android.util.Pair; import android.util.Slog; +import android.util.SparseArray; import android.util.SparseBooleanArray; -import android.util.SparseLongArray; import android.util.TimeUtils; import android.util.Xml; import android.view.Display; @@ -177,7 +180,13 @@ public class DeviceIdleController extends SystemService * List of end times for UIDs that are temporarily marked as being allowed to access * the network and acquire wakelocks. Times are in milliseconds. */ - private final SparseLongArray mTempWhitelistAppIdEndTimes = new SparseLongArray(); + private final SparseArray<Pair<MutableLong, String>> mTempWhitelistAppIdEndTimes + = new SparseArray<>(); + + /** + * Callback to the NetworkPolicyManagerService to tell it that the temp whitelist has changed. + */ + Runnable mNetworkPolicyTempWhitelistCallback; /** * Current app IDs of temporarily whitelist apps for high-priority messages. @@ -242,6 +251,8 @@ public class DeviceIdleController extends SystemService private static final String KEY_MIN_TIME_TO_ALARM = "min_time_to_alarm"; private static final String KEY_MAX_TEMP_APP_WHITELIST_DURATION = "max_temp_app_whitelist_duration"; + private static final String KEY_MMS_TEMP_APP_WHITELIST_DURATION = + "mms_temp_app_whitelist_duration"; /** * This is the time, after becoming inactive, at which we start looking at the @@ -339,6 +350,13 @@ public class DeviceIdleController extends SystemService */ public long MAX_TEMP_APP_WHITELIST_DURATION; + /** + * Amount of time we would like to whitelist an app that is receiving an MMS. + * @see Settings.Global#DEVICE_IDLE_CONSTANTS + * @see #KEY_MMS_TEMP_APP_WHITELIST_DURATION + */ + public long MMS_TEMP_APP_WHITELIST_DURATION; + private final ContentResolver mResolver; private final KeyValueListParser mParser = new KeyValueListParser(','); @@ -388,8 +406,10 @@ public class DeviceIdleController extends SystemService 2f); MIN_TIME_TO_ALARM = mParser.getLong(KEY_MIN_TIME_TO_ALARM, !COMPRESS_TIME ? 60 * 60 * 1000L : 6 * 60 * 1000L); - MAX_TEMP_APP_WHITELIST_DURATION = mParser.getLong(KEY_MAX_TEMP_APP_WHITELIST_DURATION, - 5 * 60 * 1000L); + MAX_TEMP_APP_WHITELIST_DURATION = mParser.getLong( + KEY_MAX_TEMP_APP_WHITELIST_DURATION, 5 * 60 * 1000L); + MMS_TEMP_APP_WHITELIST_DURATION = mParser.getLong( + KEY_MMS_TEMP_APP_WHITELIST_DURATION, 30 * 1000L); } } @@ -441,6 +461,10 @@ public class DeviceIdleController extends SystemService pw.print(" "); pw.print(KEY_MAX_TEMP_APP_WHITELIST_DURATION); pw.print("="); TimeUtils.formatDuration(MAX_TEMP_APP_WHITELIST_DURATION, pw); pw.println(); + + pw.print(" "); pw.print(KEY_MMS_TEMP_APP_WHITELIST_DURATION); pw.print("="); + TimeUtils.formatDuration(MMS_TEMP_APP_WHITELIST_DURATION, pw); + pw.println(); } } @@ -565,7 +589,7 @@ public class DeviceIdleController extends SystemService } @Override public void addPowerSaveTempWhitelistApp(String packageName, long duration, - int userId) throws RemoteException { + int userId, String reason) throws RemoteException { getContext().enforceCallingPermission( Manifest.permission.CHANGE_DEVICE_IDLE_TEMP_WHITELIST, "No permission to change device idle whitelist"); @@ -580,12 +604,19 @@ public class DeviceIdleController extends SystemService final long token = Binder.clearCallingIdentity(); try { DeviceIdleController.this.addPowerSaveTempWhitelistAppInternal(callingUid, - packageName, duration, userId); + packageName, duration, userId, true, reason); } finally { Binder.restoreCallingIdentity(token); } } + @Override public long addPowerSaveTempWhitelistAppForMms(String packageName, + int userId, String reason) throws RemoteException { + long duration = mConstants.MMS_TEMP_APP_WHITELIST_DURATION; + addPowerSaveTempWhitelistApp(packageName, duration, userId, reason); + return duration; + } + @Override public void exitIdle(String reason) { getContext().enforceCallingOrSelfPermission(android.Manifest.permission.DEVICE_POWER, null); @@ -598,8 +629,13 @@ public class DeviceIdleController extends SystemService } public final class LocalService { - public void addPowerSaveTempWhitelistAppDirect(int appId, long duration) { - addPowerSaveTempWhitelistAppDirectInternal(0, appId, duration); + public void addPowerSaveTempWhitelistAppDirect(int appId, long duration, boolean sync, + String reason) { + addPowerSaveTempWhitelistAppDirectInternal(0, appId, duration, sync, reason); + } + + public void setNetworkPolicyTempWhitelistCallback(Runnable callback) { + setNetworkPolicyTempWhitelistCallbackInternal(callback); } } @@ -777,11 +813,11 @@ public class DeviceIdleController extends SystemService * app an exemption to access network and acquire wakelocks. */ public void addPowerSaveTempWhitelistAppInternal(int callingUid, String packageName, - long duration, int userId) { + long duration, int userId, boolean sync, String reason) { try { int uid = getContext().getPackageManager().getPackageUid(packageName, userId); int appId = UserHandle.getAppId(uid); - addPowerSaveTempWhitelistAppDirectInternal(callingUid, appId, duration); + addPowerSaveTempWhitelistAppDirectInternal(callingUid, appId, duration, sync, reason); } catch (NameNotFoundException e) { } } @@ -791,8 +827,9 @@ public class DeviceIdleController extends SystemService * app an exemption to access network and acquire wakelocks. */ public void addPowerSaveTempWhitelistAppDirectInternal(int callingUid, int appId, - long duration) { + long duration, boolean sync, String reason) { final long timeNow = SystemClock.elapsedRealtime(); + Runnable networkPolicyTempWhitelistCallback = null; synchronized (this) { int callingAppId = UserHandle.getAppId(callingUid); if (callingAppId >= Process.FIRST_APPLICATION_UID) { @@ -802,19 +839,45 @@ public class DeviceIdleController extends SystemService } } duration = Math.min(duration, mConstants.MAX_TEMP_APP_WHITELIST_DURATION); - long currentEndTime = mTempWhitelistAppIdEndTimes.get(appId); + Pair<MutableLong, String> entry = mTempWhitelistAppIdEndTimes.get(appId); + final boolean newEntry = entry == null; // Set the new end time - mTempWhitelistAppIdEndTimes.put(appId, timeNow + duration); + if (newEntry) { + entry = new Pair<>(new MutableLong(0), reason); + mTempWhitelistAppIdEndTimes.put(appId, entry); + } + entry.first.value = timeNow + duration; if (DEBUG) { Slog.d(TAG, "Adding AppId " + appId + " to temp whitelist"); } - if (currentEndTime == 0) { + if (newEntry) { // No pending timeout for the app id, post a delayed message + try { + mBatteryStats.noteEvent(BatteryStats.HistoryItem.EVENT_TEMP_WHITELIST_START, + reason, appId); + } catch (RemoteException e) { + } postTempActiveTimeoutMessage(appId, duration); updateTempWhitelistAppIdsLocked(); + if (mNetworkPolicyTempWhitelistCallback != null) { + if (!sync) { + mHandler.post(mNetworkPolicyTempWhitelistCallback); + } else { + networkPolicyTempWhitelistCallback = mNetworkPolicyTempWhitelistCallback; + } + } reportTempWhitelistChangedLocked(); } } + if (networkPolicyTempWhitelistCallback != null) { + networkPolicyTempWhitelistCallback.run(); + } + } + + public void setNetworkPolicyTempWhitelistCallbackInternal(Runnable callback) { + synchronized (this) { + mNetworkPolicyTempWhitelistCallback = callback; + } } private void postTempActiveTimeoutMessage(int uid, long delay) { @@ -825,21 +888,26 @@ public class DeviceIdleController extends SystemService void checkTempAppWhitelistTimeout(int uid) { final long timeNow = SystemClock.elapsedRealtime(); synchronized (this) { - long endTime = mTempWhitelistAppIdEndTimes.get(uid); - if (endTime == 0) { + Pair<MutableLong, String> entry = mTempWhitelistAppIdEndTimes.get(uid); + if (entry == null) { // Nothing to do return; } - if (timeNow >= endTime) { + if (timeNow >= entry.first.value) { mTempWhitelistAppIdEndTimes.delete(uid); if (DEBUG) { Slog.d(TAG, "Removing UID " + uid + " from temp whitelist"); } updateTempWhitelistAppIdsLocked(); reportTempWhitelistChangedLocked(); + try { + mBatteryStats.noteEvent(BatteryStats.HistoryItem.EVENT_TEMP_WHITELIST_FINISH, + entry.second, uid); + } catch (RemoteException e) { + } } else { // Need more time - postTempActiveTimeoutMessage(uid, endTime - timeNow); + postTempActiveTimeoutMessage(uid, entry.first.value - timeNow); } } } @@ -1101,7 +1169,7 @@ public class DeviceIdleController extends SystemService } void readConfigFileLocked() { - Slog.d(TAG, "Reading config from " + mConfigFile.getBaseFile()); + if (DEBUG) Slog.d(TAG, "Reading config from " + mConfigFile.getBaseFile()); mPowerSaveWhitelistUserApps.clear(); FileInputStream stream; try { @@ -1370,11 +1438,14 @@ public class DeviceIdleController extends SystemService while (i < args.length) { arg = args[i]; i++; - addPowerSaveTempWhitelistAppInternal(0, arg, 10000L, userId); + addPowerSaveTempWhitelistAppInternal(0, arg, 10000L, userId, true, + "shell"); + pw.println("Added: " + arg); } } finally { Binder.restoreCallingIdentity(token); } + return; } else if (arg.length() > 0 && arg.charAt(0) == '-'){ pw.println("Unknown option: " + arg); return; @@ -1421,8 +1492,10 @@ public class DeviceIdleController extends SystemService pw.print(" UID="); pw.print(mTempWhitelistAppIdEndTimes.keyAt(i)); pw.print(": "); - TimeUtils.formatDuration(mTempWhitelistAppIdEndTimes.valueAt(i), timeNow, pw); - pw.println(); + Pair<MutableLong, String> entry = mTempWhitelistAppIdEndTimes.valueAt(i); + TimeUtils.formatDuration(entry.first.value, timeNow, pw); + pw.print(" - "); + pw.println(entry.second); } } size = mTempWhitelistAppIdArray != null ? mTempWhitelistAppIdArray.length : 0; diff --git a/services/core/java/com/android/server/am/BroadcastQueue.java b/services/core/java/com/android/server/am/BroadcastQueue.java index 7766539..91d97ef 100644 --- a/services/core/java/com/android/server/am/BroadcastQueue.java +++ b/services/core/java/com/android/server/am/BroadcastQueue.java @@ -175,7 +175,7 @@ public final class BroadcastQueue { DeviceIdleController.LocalService dic = mService.mLocalDeviceIdleController; if (dic != null) { dic.addPowerSaveTempWhitelistAppDirect(UserHandle.getAppId(msg.arg1), - msg.arg2); + msg.arg2, true, (String)msg.obj); } } break; } @@ -612,7 +612,7 @@ public final class BroadcastQueue { } } - final void scheduleTempWhitelistLocked(int uid, long duration) { + final void scheduleTempWhitelistLocked(int uid, long duration, BroadcastRecord r) { if (duration > Integer.MAX_VALUE) { duration = Integer.MAX_VALUE; } @@ -622,7 +622,19 @@ public final class BroadcastQueue { // not that big a deal, however, because the main purpose here is to allow apps // to hold wake locks, and they will be able to acquire their wake lock immediately // it just won't be enabled until we get through this work. - mHandler.obtainMessage(SCHEDULE_TEMP_WHITELIST_MSG, uid, (int)duration).sendToTarget(); + StringBuilder b = new StringBuilder(); + b.append("broadcast:"); + UserHandle.formatUid(b, r.callingUid); + b.append(":"); + if (r.intent.getAction() != null) { + b.append(r.intent.getAction()); + } else if (r.intent.getComponent() != null) { + b.append(r.intent.getComponent().flattenToShortString()); + } else if (r.intent.getData() != null) { + b.append(r.intent.getData()); + } + mHandler.obtainMessage(SCHEDULE_TEMP_WHITELIST_MSG, uid, (int)duration, b.toString()) + .sendToTarget(); } final void processNextBroadcast(boolean fromMsg) { @@ -822,7 +834,7 @@ public final class BroadcastQueue { } else { if (brOptions != null && brOptions.getTemporaryAppWhitelistDuration() > 0) { scheduleTempWhitelistLocked(filter.owningUid, - brOptions.getTemporaryAppWhitelistDuration()); + brOptions.getTemporaryAppWhitelistDuration(), r); } } return; @@ -1005,7 +1017,7 @@ public final class BroadcastQueue { if (brOptions != null && brOptions.getTemporaryAppWhitelistDuration() > 0) { scheduleTempWhitelistLocked(receiverUid, - brOptions.getTemporaryAppWhitelistDuration()); + brOptions.getTemporaryAppWhitelistDuration(), r); } // Broadcast is being executed, its package can't be stopped. diff --git a/services/core/java/com/android/server/net/NetworkPolicyManagerService.java b/services/core/java/com/android/server/net/NetworkPolicyManagerService.java index f8f00ef..395aa27 100644 --- a/services/core/java/com/android/server/net/NetworkPolicyManagerService.java +++ b/services/core/java/com/android/server/net/NetworkPolicyManagerService.java @@ -147,6 +147,7 @@ import android.util.SparseIntArray; import android.util.TrustedTime; import android.util.Xml; +import com.android.server.DeviceIdleController; import com.android.server.EventLogTags; import libcore.io.IoUtils; @@ -462,9 +463,12 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { // listen for changes to power save whitelist final IntentFilter whitelistFilter = new IntentFilter( PowerManager.ACTION_POWER_SAVE_WHITELIST_CHANGED); - whitelistFilter.addAction(PowerManager.ACTION_POWER_SAVE_TEMP_WHITELIST_CHANGED); mContext.registerReceiver(mPowerSaveWhitelistReceiver, whitelistFilter, null, mHandler); + DeviceIdleController.LocalService deviceIdleService + = LocalServices.getService(DeviceIdleController.LocalService.class); + deviceIdleService.setNetworkPolicyTempWhitelistCallback(mTempPowerSaveChangedCallback); + // watch for network interfaces to be claimed final IntentFilter connFilter = new IntentFilter(CONNECTIVITY_ACTION); mContext.registerReceiver(mConnReceiver, connFilter, CONNECTIVITY_INTERNAL, mHandler); @@ -512,7 +516,7 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { } - private IUidObserver mUidObserver = new IUidObserver.Stub() { + final private IUidObserver mUidObserver = new IUidObserver.Stub() { @Override public void onUidStateChanged(int uid, int procState) throws RemoteException { synchronized (mRulesLock) { updateUidStateLocked(uid, procState); @@ -526,24 +530,29 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { } }; - private BroadcastReceiver mPowerSaveWhitelistReceiver = new BroadcastReceiver() { + final private BroadcastReceiver mPowerSaveWhitelistReceiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { // on background handler thread, and POWER_SAVE_WHITELIST_CHANGED is protected synchronized (mRulesLock) { - if (PowerManager.ACTION_POWER_SAVE_WHITELIST_CHANGED.equals(intent.getAction())) { - updatePowerSaveWhitelistLocked(); - updateRulesForGlobalChangeLocked(false); - } else { - updatePowerSaveTempWhitelistLocked(); - updateRulesForTempWhitelistChangeLocked(); - purgePowerSaveTempWhitelistLocked(); - } + updatePowerSaveWhitelistLocked(); + updateRulesForGlobalChangeLocked(false); } } }; - private BroadcastReceiver mScreenReceiver = new BroadcastReceiver() { + final private Runnable mTempPowerSaveChangedCallback = new Runnable() { + @Override + public void run() { + synchronized (mRulesLock) { + updatePowerSaveTempWhitelistLocked(); + updateRulesForTempWhitelistChangeLocked(); + purgePowerSaveTempWhitelistLocked(); + } + } + }; + + final private BroadcastReceiver mScreenReceiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { // screen-related broadcasts are protected by system, no need @@ -552,7 +561,7 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { } }; - private BroadcastReceiver mPackageReceiver = new BroadcastReceiver() { + final private BroadcastReceiver mPackageReceiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { // on background handler thread, and PACKAGE_ADDED is protected @@ -572,7 +581,7 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { } }; - private BroadcastReceiver mUidRemovedReceiver = new BroadcastReceiver() { + final private BroadcastReceiver mUidRemovedReceiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { // on background handler thread, and UID_REMOVED is protected @@ -590,7 +599,7 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { } }; - private BroadcastReceiver mUserReceiver = new BroadcastReceiver() { + final private BroadcastReceiver mUserReceiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { // on background handler thread, and USER_ADDED and USER_REMOVED @@ -619,7 +628,7 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { * Receiver that watches for {@link INetworkStatsService} updates, which we * use to check against {@link NetworkPolicy#warningBytes}. */ - private BroadcastReceiver mStatsReceiver = new BroadcastReceiver() { + final private BroadcastReceiver mStatsReceiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { // on background handler thread, and verified @@ -637,7 +646,7 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { * Receiver that watches for {@link Notification} control of * {@link #mRestrictBackground}. */ - private BroadcastReceiver mAllowReceiver = new BroadcastReceiver() { + final private BroadcastReceiver mAllowReceiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { // on background handler thread, and verified MANAGE_NETWORK_POLICY @@ -651,7 +660,7 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { * Receiver that watches for {@link Notification} control of * {@link NetworkPolicy#lastWarningSnooze}. */ - private BroadcastReceiver mSnoozeWarningReceiver = new BroadcastReceiver() { + final private BroadcastReceiver mSnoozeWarningReceiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { // on background handler thread, and verified MANAGE_NETWORK_POLICY @@ -665,7 +674,7 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { /** * Receiver that watches for {@link WifiConfiguration} to be changed. */ - private BroadcastReceiver mWifiConfigReceiver = new BroadcastReceiver() { + final private BroadcastReceiver mWifiConfigReceiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { // on background handler thread, and verified CONNECTIVITY_INTERNAL @@ -692,7 +701,7 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { * Receiver that watches {@link WifiInfo} state changes to infer metered * state. Ignores hints when policy is user-defined. */ - private BroadcastReceiver mWifiStateReceiver = new BroadcastReceiver() { + final private BroadcastReceiver mWifiStateReceiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { // on background handler thread, and verified CONNECTIVITY_INTERNAL @@ -732,7 +741,8 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { /** * Observer that watches for {@link INetworkManagementService} alerts. */ - private INetworkManagementEventObserver mAlertObserver = new BaseNetworkObserver() { + final private INetworkManagementEventObserver mAlertObserver + = new BaseNetworkObserver() { @Override public void limitReached(String limitName, String iface) { // only someone like NMS should be calling us @@ -1985,6 +1995,10 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { // state changed, push updated rules mUidState.put(uid, uidState); updateRulesForUidStateChangeLocked(uid, oldUidState, uidState); + if (mDeviceIdleMode && isProcStateAllowedWhileIdle(oldUidState) + != isProcStateAllowedWhileIdle(uidState)) { + updateRulesForDeviceIdleLocked(); + } } } @@ -1996,6 +2010,9 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { if (oldUidState != ActivityManager.PROCESS_STATE_CACHED_EMPTY) { updateRulesForUidStateChangeLocked(uid, oldUidState, ActivityManager.PROCESS_STATE_CACHED_EMPTY); + if (mDeviceIdleMode) { + updateRulesForDeviceIdleLocked(); + } } } } @@ -2033,13 +2050,18 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { } } + static boolean isProcStateAllowedWhileIdle(int procState) { + return procState <= ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE; + } + void updateRulesForDeviceIdleLocked() { if (mDeviceIdleMode) { // sync the whitelists before enable dozable chain. We don't care about the rules if // we are disabling the chain. SparseIntArray uidRules = new SparseIntArray(); final List<UserInfo> users = mUserManager.getUsers(); - for (UserInfo user : users) { + for (int ui = users.size() - 1; ui >= 0; ui--) { + UserInfo user = users.get(ui); for (int i = mPowerSaveTempWhitelistAppIds.size() - 1; i >= 0; i--) { int appId = mPowerSaveTempWhitelistAppIds.keyAt(i); int uid = UserHandle.getUid(user.id, appId); @@ -2051,6 +2073,11 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { uidRules.put(uid, FIREWALL_RULE_ALLOW); } } + for (int i = mUidState.size() - 1; i >= 0; i--) { + if (isProcStateAllowedWhileIdle(mUidState.valueAt(i))) { + uidRules.put(mUidState.keyAt(i), FIREWALL_RULE_ALLOW); + } + } setUidFirewallRules(FIREWALL_CHAIN_DOZABLE, uidRules); } enableFirewallChainLocked(FIREWALL_CHAIN_DOZABLE, mDeviceIdleMode); diff --git a/services/usage/java/com/android/server/usage/UsageStatsService.java b/services/usage/java/com/android/server/usage/UsageStatsService.java index c49a5f9..b0a14c8 100644 --- a/services/usage/java/com/android/server/usage/UsageStatsService.java +++ b/services/usage/java/com/android/server/usage/UsageStatsService.java @@ -1177,7 +1177,11 @@ public class UsageStatsService extends SystemService implements @Override public void whitelistAppTemporarily(String packageName, long duration, int userId) throws RemoteException { - mDeviceIdleController.addPowerSaveTempWhitelistApp(packageName, duration, userId); + StringBuilder reason = new StringBuilder(32); + reason.append("from:"); + UserHandle.formatUid(reason, Binder.getCallingUid()); + mDeviceIdleController.addPowerSaveTempWhitelistApp(packageName, duration, userId, + reason.toString()); } @Override diff --git a/test-runner/src/android/test/mock/MockContext.java b/test-runner/src/android/test/mock/MockContext.java index e5ea562..e09d124 100644 --- a/test-runner/src/android/test/mock/MockContext.java +++ b/test-runner/src/android/test/mock/MockContext.java @@ -395,13 +395,19 @@ public class MockContext extends Context { @Override public void sendOrderedBroadcastAsUser(Intent intent, UserHandle user, String receiverPermission, int appOp, BroadcastReceiver resultReceiver, - Handler scheduler, - int initialCode, String initialData, Bundle initialExtras) { + Handler scheduler, int initialCode, String initialData, Bundle initialExtras) { throw new UnsupportedOperationException(); } + /** @hide */ @Override + public void sendOrderedBroadcastAsUser(Intent intent, UserHandle user, + String receiverPermission, int appOp, Bundle options, BroadcastReceiver resultReceiver, + Handler scheduler, int initialCode, String initialData, Bundle initialExtras) { + throw new UnsupportedOperationException(); + } + @Override public void sendStickyBroadcast(Intent intent) { throw new UnsupportedOperationException(); } diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContext.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContext.java index 933420f..1f3802e 100644 --- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContext.java +++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContext.java @@ -1586,6 +1586,14 @@ public final class BridgeContext extends Context { } @Override + public void sendOrderedBroadcastAsUser(Intent intent, UserHandle user, + String receiverPermission, int appOp, Bundle options, BroadcastReceiver resultReceiver, + Handler scheduler, + int initialCode, String initialData, Bundle initialExtras) { + // pass + } + + @Override public void sendStickyBroadcast(Intent arg0) { // pass |