diff options
author | Amith Yamasani <yamasani@google.com> | 2015-04-24 19:06:07 -0700 |
---|---|---|
committer | Amith Yamasani <yamasani@google.com> | 2015-04-29 14:21:53 -0700 |
commit | 15e47235c055495ec0ccc24768a6746a960d3a61 (patch) | |
tree | 434a82a8c5dc409f0f3ae62f91adc7144e2d371e /services/usage/java/com/android/server | |
parent | 9ac2718e7dcf274ad41fbb374bedabadc558634b (diff) | |
download | frameworks_base-15e47235c055495ec0ccc24768a6746a960d3a61.zip frameworks_base-15e47235c055495ec0ccc24768a6746a960d3a61.tar.gz frameworks_base-15e47235c055495ec0ccc24768a6746a960d3a61.tar.bz2 |
Remove network access for idle apps
Track apps going in and out of idle in the NetworkPolicyManagerService.
Apply DROP rules in firewall controller if app is to be blacklisted
for network access.
Firewall can now be in whitelist (old) or blacklist mode. When in
blacklist, it allows all by default and we can selectively DENY
some uids.
Track app idle in UsageStats and update periodically.
Track charging/discharging states.
TODO: Check for appidle temporary parole state
Bug: 20066058
Change-Id: Ia65d7544204b3bcb78a517310ef4adcc05aac6fb
Diffstat (limited to 'services/usage/java/com/android/server')
-rw-r--r-- | services/usage/java/com/android/server/usage/UsageStatsService.java | 106 |
1 files changed, 95 insertions, 11 deletions
diff --git a/services/usage/java/com/android/server/usage/UsageStatsService.java b/services/usage/java/com/android/server/usage/UsageStatsService.java index 04984d3..c2e61c6 100644 --- a/services/usage/java/com/android/server/usage/UsageStatsService.java +++ b/services/usage/java/com/android/server/usage/UsageStatsService.java @@ -28,7 +28,6 @@ import android.app.usage.UsageEvents.Event; import android.app.usage.UsageStats; import android.app.usage.UsageStatsManagerInternal; import android.app.usage.UsageStatsManagerInternal.AppIdleStateChangeListener; -import android.appwidget.AppWidgetManager; import android.content.BroadcastReceiver; import android.content.ComponentName; import android.content.Context; @@ -41,6 +40,7 @@ import android.content.pm.UserInfo; import android.content.res.Configuration; import android.database.ContentObserver; import android.net.Uri; +import android.os.BatteryManager; import android.os.Binder; import android.os.Environment; import android.os.Handler; @@ -81,6 +81,8 @@ public class UsageStatsService extends SystemService implements private static final long TWENTY_MINUTES = 20 * 60 * 1000; private static final long FLUSH_INTERVAL = DEBUG ? TEN_SECONDS : TWENTY_MINUTES; private static final long TIME_CHANGE_THRESHOLD_MILLIS = 2 * 1000; // Two seconds. + static final long DEFAULT_APP_IDLE_THRESHOLD_MILLIS = 2L * 24 * 60 * 60 * 1000; // 1 day + static final long DEFAULT_CHECK_IDLE_INTERVAL = 8 * 3600 * 1000; // 8 hours // Handler message types. static final int MSG_REPORT_EVENT = 0; @@ -88,6 +90,7 @@ public class UsageStatsService extends SystemService implements static final int MSG_REMOVE_USER = 2; static final int MSG_INFORM_LISTENERS = 3; static final int MSG_RESET_LAST_TIMESTAMP = 4; + static final int MSG_CHECK_IDLE_STATES = 5; private final Object mLock = new Object(); Handler mHandler; @@ -98,9 +101,11 @@ public class UsageStatsService extends SystemService implements private File mUsageStatsDir; long mRealTimeSnapshot; long mSystemTimeSnapshot; + boolean mAppIdleParoled; - private static final long DEFAULT_APP_IDLE_THRESHOLD_MILLIS = 1L * 24 * 60 * 60 * 1000; // 1 day - private long mAppIdleDurationMillis; + long mAppIdleDurationMillis; + + long mCheckIdleIntervalMillis = DEFAULT_CHECK_IDLE_INTERVAL; private ArrayList<UsageStatsManagerInternal.AppIdleStateChangeListener> mPackageAccessListeners = new ArrayList<>(); @@ -113,6 +118,7 @@ public class UsageStatsService extends SystemService implements public void onStart() { mAppOps = (AppOpsManager) getContext().getSystemService(Context.APP_OPS_SERVICE); mUserManager = (UserManager) getContext().getSystemService(Context.USER_SERVICE); + mHandler = new H(BackgroundThread.get().getLooper()); File systemDataDir = new File(Environment.getDataDirectory(), "system"); @@ -123,9 +129,14 @@ public class UsageStatsService extends SystemService implements + mUsageStatsDir.getAbsolutePath()); } - getContext().registerReceiver(new UserRemovedReceiver(), - new IntentFilter(Intent.ACTION_USER_REMOVED)); + IntentFilter userActions = new IntentFilter(Intent.ACTION_USER_REMOVED); + userActions.addAction(Intent.ACTION_USER_STARTED); + getContext().registerReceiverAsUser(new UserActionsReceiver(), UserHandle.ALL, userActions, + null, null); + IntentFilter deviceStates = new IntentFilter(BatteryManager.ACTION_CHARGING); + deviceStates.addAction(BatteryManager.ACTION_DISCHARGING); + getContext().registerReceiver(new DeviceStateReceiver(), deviceStates); synchronized (mLock) { cleanUpRemovedUsersLocked(); } @@ -147,18 +158,35 @@ public class UsageStatsService extends SystemService implements if (phase == PHASE_SYSTEM_SERVICES_READY) { // Observe changes to the threshold new SettingsObserver(mHandler).registerObserver(); + } else if (phase == PHASE_BOOT_COMPLETED) { + setAppIdleParoled(getContext().getSystemService(BatteryManager.class).isCharging()); } } - private class UserRemovedReceiver extends BroadcastReceiver { + private class UserActionsReceiver extends BroadcastReceiver { @Override public void onReceive(Context context, Intent intent) { - if (intent != null && intent.getAction().equals(Intent.ACTION_USER_REMOVED)) { - final int userId = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, -1); + final int userId = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, -1); + if (Intent.ACTION_USER_REMOVED.equals(intent.getAction())) { if (userId >= 0) { mHandler.obtainMessage(MSG_REMOVE_USER, userId, 0).sendToTarget(); } + } else if (Intent.ACTION_USER_STARTED.equals(intent.getAction())) { + if (userId >=0) { + postCheckIdleStates(); + } + } + } + } + + private class DeviceStateReceiver extends BroadcastReceiver { + @Override + public void onReceive(Context context, Intent intent) { + final String action = intent.getAction(); + if (BatteryManager.ACTION_CHARGING.equals(action) + || BatteryManager.ACTION_DISCHARGING.equals(action)) { + setAppIdleParoled(BatteryManager.ACTION_CHARGING.equals(action)); } } } @@ -195,6 +223,49 @@ public class UsageStatsService extends SystemService implements } } + void setAppIdleParoled(boolean paroled) { + synchronized (mLock) { + if (mAppIdleParoled != paroled) { + mAppIdleParoled = paroled; + postCheckIdleStates(); + } + } + } + + void postCheckIdleStates() { + mHandler.removeMessages(MSG_CHECK_IDLE_STATES); + mHandler.sendEmptyMessage(MSG_CHECK_IDLE_STATES); + } + + /** Check all running users' apps to see if they enter an idle state. */ + void checkIdleStates() { + final int[] runningUsers; + try { + runningUsers = ActivityManagerNative.getDefault().getRunningUserIds(); + } catch (RemoteException re) { + return; + } + + for (int i = 0; i < runningUsers.length; i++) { + final int userId = runningUsers[i]; + List<PackageInfo> packages = + getContext().getPackageManager().getInstalledPackages( + PackageManager.GET_DISABLED_COMPONENTS + | PackageManager.GET_UNINSTALLED_PACKAGES, + userId); + synchronized (mLock) { + final int packageCount = packages.size(); + for (int p = 0; p < packageCount; p++) { + final String packageName = packages.get(p).packageName; + final boolean isIdle = isAppIdle(packageName, userId); + mHandler.sendMessage(mHandler.obtainMessage(MSG_INFORM_LISTENERS, + userId, isIdle ? 1 : 0, packageName)); + } + } + } + mHandler.sendEmptyMessageDelayed(MSG_CHECK_IDLE_STATES, mCheckIdleIntervalMillis); + } + private static void deleteRecursively(File f) { File[] files = f.listFiles(); if (files != null) { @@ -291,7 +362,7 @@ public class UsageStatsService extends SystemService implements void resetLastTimestamp(String packageName, int userId, boolean idle) { synchronized (mLock) { final long timeNow = checkAndGetTimeLocked(); - final long lastTimestamp = timeNow - (idle ? mAppIdleDurationMillis : 0); + final long lastTimestamp = timeNow - (idle ? mAppIdleDurationMillis : 0) - 5000; final UserUsageStatsService service = getUserDataAndInitializeIfNeededLocked(userId, timeNow); @@ -409,14 +480,22 @@ public class UsageStatsService extends SystemService implements private boolean hasPassedIdleDuration(long lastUsed) { final long now = System.currentTimeMillis(); - return lastUsed < now - mAppIdleDurationMillis; + return lastUsed <= now - mAppIdleDurationMillis; } boolean isAppIdle(String packageName, int userId) { if (packageName == null) return false; + synchronized (mLock) { + // Temporary exemption, probably due to device charging or occasional allowance to + // be allowed to sync, etc. + if (mAppIdleParoled) { + return false; + } + } if (SystemConfig.getInstance().getAllowInPowerSave().contains(packageName)) { return false; } + // TODO: Optimize this check if (isActiveDeviceAdmin(packageName, userId)) { return false; } @@ -518,6 +597,9 @@ public class UsageStatsService extends SystemService implements resetLastTimestamp((String) msg.obj, msg.arg1, msg.arg2 == 1); break; + case MSG_CHECK_IDLE_STATES: + checkIdleStates(); + break; default: super.handleMessage(msg); break; @@ -544,7 +626,9 @@ public class UsageStatsService extends SystemService implements mAppIdleDurationMillis = Settings.Secure.getLongForUser(getContext().getContentResolver(), Settings.Secure.APP_IDLE_DURATION, DEFAULT_APP_IDLE_THRESHOLD_MILLIS, UserHandle.USER_OWNER); - // TODO: Check if we need to update idle states of all the apps + mCheckIdleIntervalMillis = Math.min(DEFAULT_CHECK_IDLE_INTERVAL, + mAppIdleDurationMillis / 4); + postCheckIdleStates(); } } |