diff options
author | Dianne Hackborn <hackbod@google.com> | 2015-07-01 15:05:04 -0700 |
---|---|---|
committer | Dianne Hackborn <hackbod@google.com> | 2015-07-01 15:05:04 -0700 |
commit | 3b16cf4f47142a845bf0ede54ef8ef956506c6c3 (patch) | |
tree | 5f1ae1b8de0e604078af0ea8a360d217b16bce6b /services/core/java | |
parent | 80abf887a1578669d3167ea83d52a497a64ea491 (diff) | |
download | frameworks_base-3b16cf4f47142a845bf0ede54ef8ef956506c6c3.zip frameworks_base-3b16cf4f47142a845bf0ede54ef8ef956506c6c3.tar.gz frameworks_base-3b16cf4f47142a845bf0ede54ef8ef956506c6c3.tar.bz2 |
Device idle fixes: issue #22209630 and issue #22225665
Issue #22209630: Only allow whitelisted apps to put apps on the temp whitelist
We now check whether the calling app is a system uid or in the whitelist
and, if not, throw an exception.
Issue #22225665: Alarm still goes off in idle mode (doze)
Fix a bug where we were not clearing the calling identity when coming
through the dump command to the service, and as a result when we would
eventually call out to the alarm manager it wouldn't do what we want.
This was only broken when being controlled by the shell.
Also adjust the network policy manager service's handling of device
idle transitions to only toggle the device idle state, which gets rid
of the long delay we have coming out of idle mode. And add in a bit
of logging around going in/out of idle mode to try to understand where
things may be slow in the future.
Change-Id: I4a41f790e9b0bb31330314b94111557d479f2ba5
Diffstat (limited to 'services/core/java')
4 files changed, 130 insertions, 65 deletions
diff --git a/services/core/java/com/android/server/DeviceIdleController.java b/services/core/java/com/android/server/DeviceIdleController.java index dc203ff..c8dc565 100644 --- a/services/core/java/com/android/server/DeviceIdleController.java +++ b/services/core/java/com/android/server/DeviceIdleController.java @@ -158,15 +158,20 @@ public class DeviceIdleController extends SystemService private final ArrayMap<String, Integer> mPowerSaveWhitelistUserApps = new ArrayMap<>(); /** + * App IDs of built-in system apps that have been white-listed. + */ + private final SparseBooleanArray mPowerSaveWhitelistSystemAppIds = new SparseBooleanArray(); + + /** * App IDs that have been white-listed to opt out of power save restrictions. */ - private final SparseBooleanArray mPowerSaveWhitelistAppIds = new SparseBooleanArray(); + private final SparseBooleanArray mPowerSaveWhitelistAllAppIds = new SparseBooleanArray(); /** * Current app IDs that are in the complete power save white list. This array can * be shared with others because it will not be modified once set. */ - private int[] mPowerSaveWhitelistAppIdArray = new int[0]; + private int[] mPowerSaveWhitelistAllAppIdArray = new int[0]; /** * List of end times for UIDs that are temporarily marked as being allowed to access @@ -478,6 +483,7 @@ public class DeviceIdleController extends SystemService handleWriteConfigFile(); } break; case MSG_REPORT_IDLE_ON: { + EventLogTags.writeDeviceIdleOnStart(); mLocalPowerManager.setDeviceIdleMode(true); try { mNetworkPolicyManager.setDeviceIdleMode(true); @@ -485,8 +491,10 @@ public class DeviceIdleController extends SystemService } catch (RemoteException e) { } getContext().sendBroadcastAsUser(mIdleIntent, UserHandle.ALL); + EventLogTags.writeDeviceIdleOnComplete(); } break; case MSG_REPORT_IDLE_OFF: { + EventLogTags.writeDeviceIdleOffStart("unknown"); mLocalPowerManager.setDeviceIdleMode(false); try { mNetworkPolicyManager.setDeviceIdleMode(false); @@ -494,11 +502,14 @@ public class DeviceIdleController extends SystemService } catch (RemoteException e) { } getContext().sendBroadcastAsUser(mIdleIntent, UserHandle.ALL); + EventLogTags.writeDeviceIdleOffComplete(); } break; case MSG_REPORT_ACTIVE: { String activeReason = (String)msg.obj; int activeUid = msg.arg1; boolean needBroadcast = msg.arg2 != 0; + EventLogTags.writeDeviceIdleOffStart( + activeReason != null ? activeReason : "unknown"); mLocalPowerManager.setDeviceIdleMode(false); try { mNetworkPolicyManager.setDeviceIdleMode(false); @@ -508,6 +519,7 @@ public class DeviceIdleController extends SystemService if (needBroadcast) { getContext().sendBroadcastAsUser(mIdleIntent, UserHandle.ALL); } + EventLogTags.writeDeviceIdleOffComplete(); } break; case MSG_TEMP_APP_WHITELIST_TIMEOUT: { int uid = msg.arg1; @@ -557,17 +569,18 @@ public class DeviceIdleController extends SystemService getContext().enforceCallingPermission( Manifest.permission.CHANGE_DEVICE_IDLE_TEMP_WHITELIST, "No permission to change device idle whitelist"); + final int callingUid = Binder.getCallingUid(); userId = ActivityManagerNative.getDefault().handleIncomingUser( Binder.getCallingPid(), - Binder.getCallingUid(), + callingUid, userId, /*allowAll=*/ false, /*requireFull=*/ false, "addPowerSaveTempWhitelistApp", null); final long token = Binder.clearCallingIdentity(); try { - DeviceIdleController.this.addPowerSaveTempWhitelistAppInternal(packageName, - duration, userId); + DeviceIdleController.this.addPowerSaveTempWhitelistAppInternal(callingUid, + packageName, duration, userId); } finally { Binder.restoreCallingIdentity(token); } @@ -586,7 +599,7 @@ public class DeviceIdleController extends SystemService public final class LocalService { public void addPowerSaveTempWhitelistAppDirect(int appId, long duration) { - DeviceIdleController.this.addPowerSaveTempWhitelistAppDirectInternal(appId, duration); + addPowerSaveTempWhitelistAppDirectInternal(0, appId, duration); } } @@ -614,8 +627,9 @@ public class DeviceIdleController extends SystemService try { ApplicationInfo ai = pm.getApplicationInfo(pkg, 0); if ((ai.flags&ApplicationInfo.FLAG_SYSTEM) != 0) { - mPowerSaveWhitelistApps.put(ai.packageName, - UserHandle.getAppId(ai.uid)); + int appid = UserHandle.getAppId(ai.uid); + mPowerSaveWhitelistApps.put(ai.packageName, appid); + mPowerSaveWhitelistSystemAppIds.put(appid, true); } } catch (PackageManager.NameNotFoundException e) { } @@ -667,14 +681,15 @@ public class DeviceIdleController extends SystemService mSensingAlarmIntent = PendingIntent.getBroadcast(getContext(), 0, intentSensing, 0); mIdleIntent = new Intent(PowerManager.ACTION_DEVICE_IDLE_MODE_CHANGED); - mIdleIntent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY); + mIdleIntent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY + | Intent.FLAG_RECEIVER_FOREGROUND); IntentFilter filter = new IntentFilter(); filter.addAction(Intent.ACTION_BATTERY_CHANGED); filter.addAction(ACTION_STEP_IDLE_STATE); getContext().registerReceiver(mReceiver, filter); - mLocalPowerManager.setDeviceIdleWhitelist(mPowerSaveWhitelistAppIdArray); + mLocalPowerManager.setDeviceIdleWhitelist(mPowerSaveWhitelistAllAppIdArray); mDisplayManager.registerDisplayListener(mDisplayListener, null); updateDisplayLocked(); @@ -747,7 +762,7 @@ public class DeviceIdleController extends SystemService public int[] getAppIdWhitelistInternal() { synchronized (this) { - return mPowerSaveWhitelistAppIdArray; + return mPowerSaveWhitelistAllAppIdArray; } } @@ -761,12 +776,12 @@ public class DeviceIdleController extends SystemService * Adds an app to the temporary whitelist and resets the endTime for granting the * app an exemption to access network and acquire wakelocks. */ - public void addPowerSaveTempWhitelistAppInternal(String packageName, long duration, - int userId) { + public void addPowerSaveTempWhitelistAppInternal(int callingUid, String packageName, + long duration, int userId) { try { int uid = getContext().getPackageManager().getPackageUid(packageName, userId); int appId = UserHandle.getAppId(uid); - addPowerSaveTempWhitelistAppDirectInternal(appId, duration); + addPowerSaveTempWhitelistAppDirectInternal(callingUid, appId, duration); } catch (NameNotFoundException e) { } } @@ -775,9 +790,17 @@ public class DeviceIdleController extends SystemService * Adds an app to the temporary whitelist and resets the endTime for granting the * app an exemption to access network and acquire wakelocks. */ - public void addPowerSaveTempWhitelistAppDirectInternal(int appId, long duration) { + public void addPowerSaveTempWhitelistAppDirectInternal(int callingUid, int appId, + long duration) { final long timeNow = SystemClock.elapsedRealtime(); synchronized (this) { + int callingAppId = UserHandle.getAppId(callingUid); + if (callingAppId >= Process.FIRST_APPLICATION_UID) { + if (!mPowerSaveWhitelistSystemAppIds.get(callingAppId)) { + throw new SecurityException("Calling app " + UserHandle.formatUid(callingUid) + + " is not on whitelist"); + } + } duration = Math.min(duration, mConstants.MAX_TEMP_APP_WHITELIST_DURATION); long currentEndTime = mTempWhitelistAppIdEndTimes.get(appId); // Set the new end time @@ -1026,25 +1049,25 @@ public class DeviceIdleController extends SystemService } private void updateWhitelistAppIdsLocked() { - mPowerSaveWhitelistAppIds.clear(); + mPowerSaveWhitelistAllAppIds.clear(); for (int i=0; i<mPowerSaveWhitelistApps.size(); i++) { - mPowerSaveWhitelistAppIds.put(mPowerSaveWhitelistApps.valueAt(i), true); + mPowerSaveWhitelistAllAppIds.put(mPowerSaveWhitelistApps.valueAt(i), true); } for (int i=0; i<mPowerSaveWhitelistUserApps.size(); i++) { - mPowerSaveWhitelistAppIds.put(mPowerSaveWhitelistUserApps.valueAt(i), true); + mPowerSaveWhitelistAllAppIds.put(mPowerSaveWhitelistUserApps.valueAt(i), true); } - int size = mPowerSaveWhitelistAppIds.size(); + int size = mPowerSaveWhitelistAllAppIds.size(); int[] appids = new int[size]; for (int i = 0; i < size; i++) { - appids[i] = mPowerSaveWhitelistAppIds.keyAt(i); + appids[i] = mPowerSaveWhitelistAllAppIds.keyAt(i); } - mPowerSaveWhitelistAppIdArray = appids; + mPowerSaveWhitelistAllAppIdArray = appids; if (mLocalPowerManager != null) { if (DEBUG) { Slog.d(TAG, "Setting wakelock whitelist to " - + Arrays.toString(mPowerSaveWhitelistAppIdArray)); + + Arrays.toString(mPowerSaveWhitelistAllAppIdArray)); } - mLocalPowerManager.setDeviceIdleWhitelist(mPowerSaveWhitelistAppIdArray); + mLocalPowerManager.setDeviceIdleWhitelist(mPowerSaveWhitelistAllAppIdArray); } } @@ -1245,25 +1268,40 @@ public class DeviceIdleController extends SystemService // Ignore, we always dump all. } else if ("step".equals(arg)) { synchronized (this) { - stepIdleStateLocked(); - pw.print("Stepped to: "); pw.println(stateToString(mState)); + long token = Binder.clearCallingIdentity(); + try { + stepIdleStateLocked(); + pw.print("Stepped to: "); pw.println(stateToString(mState)); + } finally { + Binder.restoreCallingIdentity(token); + } } return; } else if ("disable".equals(arg)) { synchronized (this) { - if (mEnabled) { - mEnabled = false; - becomeActiveLocked("disabled", Process.myUid()); - pw.println("Idle mode disabled"); + long token = Binder.clearCallingIdentity(); + try { + if (mEnabled) { + mEnabled = false; + becomeActiveLocked("disabled", Process.myUid()); + pw.println("Idle mode disabled"); + } + } finally { + Binder.restoreCallingIdentity(token); } } return; } else if ("enable".equals(arg)) { synchronized (this) { - if (!mEnabled) { - mEnabled = true; - becomeInactiveIfAppropriateLocked(); - pw.println("Idle mode enabled"); + long token = Binder.clearCallingIdentity(); + try { + if (!mEnabled) { + mEnabled = true; + becomeInactiveIfAppropriateLocked(); + pw.println("Idle mode enabled"); + } + } finally { + Binder.restoreCallingIdentity(token); } } return; @@ -1273,40 +1311,50 @@ public class DeviceIdleController extends SystemService } return; } else if ("whitelist".equals(arg)) { - i++; - while (i < args.length) { - arg = args[i]; + long token = Binder.clearCallingIdentity(); + try { i++; - if (arg.length() < 1 || (arg.charAt(0) != '-' - && arg.charAt(0) != '+')) { - pw.println("Package must be prefixed with + or -: " + arg); - return; - } - char op = arg.charAt(0); - String pkg = arg.substring(1); - if (op == '+') { - if (addPowerSaveWhitelistAppInternal(pkg)) { - pw.println("Added: " + pkg); - } else { - pw.println("Unknown package: " + pkg); + while (i < args.length) { + arg = args[i]; + i++; + if (arg.length() < 1 || (arg.charAt(0) != '-' + && arg.charAt(0) != '+')) { + pw.println("Package must be prefixed with + or -: " + arg); + return; } - } else { - if (removePowerSaveWhitelistAppInternal(pkg)) { - pw.println("Removed: " + pkg); + char op = arg.charAt(0); + String pkg = arg.substring(1); + if (op == '+') { + if (addPowerSaveWhitelistAppInternal(pkg)) { + pw.println("Added: " + pkg); + } else { + pw.println("Unknown package: " + pkg); + } + } else { + if (removePowerSaveWhitelistAppInternal(pkg)) { + pw.println("Removed: " + pkg); + } } } + } finally { + Binder.restoreCallingIdentity(token); } return; } else if ("tempwhitelist".equals(arg)) { - i++; - if (i >= args.length) { - pw.println("At least one package name must be specified"); - return; - } - while (i < args.length) { - arg = args[i]; + long token = Binder.clearCallingIdentity(); + try { i++; - addPowerSaveTempWhitelistAppInternal(arg, 10000L, userId); + if (i >= args.length) { + pw.println("At least one package name must be specified"); + return; + } + while (i < args.length) { + arg = args[i]; + i++; + addPowerSaveTempWhitelistAppInternal(0, arg, 10000L, userId); + } + } finally { + Binder.restoreCallingIdentity(token); } } else if (arg.length() > 0 && arg.charAt(0) == '-'){ pw.println("Unknown option: " + arg); @@ -1337,12 +1385,12 @@ public class DeviceIdleController extends SystemService pw.println(mPowerSaveWhitelistUserApps.keyAt(i)); } } - size = mPowerSaveWhitelistAppIds.size(); + size = mPowerSaveWhitelistAllAppIds.size(); if (size > 0) { - pw.println(" Whitelist app ids:"); + pw.println(" Whitelist all app ids:"); for (int i = 0; i < size; i++) { pw.print(" "); - pw.print(mPowerSaveWhitelistAppIds.keyAt(i)); + pw.print(mPowerSaveWhitelistAllAppIds.keyAt(i)); pw.println(); } } diff --git a/services/core/java/com/android/server/EventLogTags.logtags b/services/core/java/com/android/server/EventLogTags.logtags index 43b640b..2842f85 100644 --- a/services/core/java/com/android/server/EventLogTags.logtags +++ b/services/core/java/com/android/server/EventLogTags.logtags @@ -183,6 +183,12 @@ option java_package com.android.server 34000 device_idle (state|1|5), (reason|3) 34001 device_idle_step 34002 device_idle_wake_from_idle (is_idle|1|5), (reason|3) +34003 device_idle_on_start +34004 device_idle_on_phase (what|3) +34005 device_idle_on_complete +34006 device_idle_off_start (reason|3) +34007 device_idle_off_phase (what|3) +34008 device_idle_off_complete # --------------------------- # DisplayManagerService.java @@ -224,8 +230,8 @@ option java_package com.android.server # --------------------------- # IdleMaintenanceService.java # --------------------------- -2753 idle_maintenance_window_start (time|2|3), (lastUserActivity|2|3), (batteryLevel|1|6), (batteryCharging|1|5) -2754 idle_maintenance_window_finish (time|2|3), (lastUserActivity|2|3), (batteryLevel|1|6), (batteryCharging|1|5) +51500 idle_maintenance_window_start (time|2|3), (lastUserActivity|2|3), (batteryLevel|1|6), (batteryCharging|1|5) +51501 idle_maintenance_window_finish (time|2|3), (lastUserActivity|2|3), (batteryLevel|1|6), (batteryCharging|1|5) # --------------------------- # MountService.java diff --git a/services/core/java/com/android/server/net/NetworkPolicyManagerService.java b/services/core/java/com/android/server/net/NetworkPolicyManagerService.java index d4b7256..f618c3e 100644 --- a/services/core/java/com/android/server/net/NetworkPolicyManagerService.java +++ b/services/core/java/com/android/server/net/NetworkPolicyManagerService.java @@ -146,6 +146,7 @@ import android.util.SparseIntArray; import android.util.TrustedTime; import android.util.Xml; +import com.android.server.EventLogTags; import libcore.io.IoUtils; import com.android.internal.R; @@ -1764,7 +1765,12 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { if (mDeviceIdleMode != enabled) { mDeviceIdleMode = enabled; if (mSystemReady) { - updateRulesForGlobalChangeLocked(true); + updateRulesForDeviceIdleLocked(); + } + if (enabled) { + EventLogTags.writeDeviceIdleOnPhase("net"); + } else { + EventLogTags.writeDeviceIdleOffPhase("net"); } } } diff --git a/services/core/java/com/android/server/power/PowerManagerService.java b/services/core/java/com/android/server/power/PowerManagerService.java index 5a0bee9..3f59755 100644 --- a/services/core/java/com/android/server/power/PowerManagerService.java +++ b/services/core/java/com/android/server/power/PowerManagerService.java @@ -2311,6 +2311,11 @@ public final class PowerManagerService extends SystemService if (mDeviceIdleMode != enabled) { mDeviceIdleMode = enabled; updateWakeLockDisabledStatesLocked(); + if (enabled) { + EventLogTags.writeDeviceIdleOnPhase("power"); + } else { + EventLogTags.writeDeviceIdleOffPhase("power"); + } } } } |