am b5148fd6: am a2c159fe: Merge "system_server: optimize app idle parole state change" into mnc-dev

* commit 'b5148fd6099ae0d6a1979dc98a3ff6ac96558b1e':
  system_server: optimize app idle parole state change
This commit is contained in:
Xiaohui Chen
2015-06-23 21:05:44 +00:00
committed by Android Git Automerger
7 changed files with 220 additions and 191 deletions

View File

@@ -76,6 +76,12 @@ public abstract class UsageStatsManagerInternal {
*/ */
public abstract boolean isAppIdle(String packageName, int userId); public abstract boolean isAppIdle(String packageName, int userId);
/**
* @return True if currently app idle parole mode is on. This means all idle apps are allow to
* run for a short period of time.
*/
public abstract boolean isAppIdleParoleOn();
/** /**
* Sets up a listener for changes to packages being accessed. * Sets up a listener for changes to packages being accessed.
* @param listener A listener within the system process. * @param listener A listener within the system process.
@@ -90,8 +96,9 @@ public abstract class UsageStatsManagerInternal {
public abstract void removeAppIdleStateChangeListener( public abstract void removeAppIdleStateChangeListener(
AppIdleStateChangeListener listener); AppIdleStateChangeListener listener);
public interface AppIdleStateChangeListener { public static abstract class AppIdleStateChangeListener {
void onAppIdleStateChanged(String packageName, int userId, boolean idle); public abstract void onAppIdleStateChanged(String packageName, int userId, boolean idle);
public abstract void onParoleStateChanged(boolean isParoleOn);
} }
} }

View File

@@ -214,9 +214,9 @@ public class NetworkManagementService extends INetworkManagementService.Stub
*/ */
@GuardedBy("mQuotaLock") @GuardedBy("mQuotaLock")
private SparseIntArray mUidFirewallDozableRules = new SparseIntArray(); private SparseIntArray mUidFirewallDozableRules = new SparseIntArray();
/** Set of states for the child firewall chains. True if the chain is active. */
private boolean mStandbyChainEnabled = false; @GuardedBy("mQuotaLock")
private boolean mDozableChainEnabled = false; final SparseBooleanArray mFirewallChainStates = new SparseBooleanArray();
private Object mIdleTimerLock = new Object(); private Object mIdleTimerLock = new Object();
/** Set of interfaces with active idle timers. */ /** Set of interfaces with active idle timers. */
@@ -307,9 +307,6 @@ public class NetworkManagementService extends INetworkManagementService.Stub
} }
public void systemReady() { public void systemReady() {
// init firewall states
mDozableChainEnabled = false;
mStandbyChainEnabled = true;
prepareNativeDaemon(); prepareNativeDaemon();
if (DBG) Slog.d(TAG, "Prepared"); if (DBG) Slog.d(TAG, "Prepared");
} }
@@ -611,7 +608,7 @@ public class NetworkManagementService extends INetworkManagementService.Stub
uidFirewallRules.valueAt(i)); uidFirewallRules.valueAt(i));
} }
} }
if (mStandbyChainEnabled) { if (mFirewallChainStates.get(FIREWALL_CHAIN_STANDBY)) {
setFirewallChainEnabled(FIREWALL_CHAIN_STANDBY, true); setFirewallChainEnabled(FIREWALL_CHAIN_STANDBY, true);
} }
@@ -625,7 +622,7 @@ public class NetworkManagementService extends INetworkManagementService.Stub
uidFirewallRules.valueAt(i)); uidFirewallRules.valueAt(i));
} }
} }
if (mDozableChainEnabled) { if (mFirewallChainStates.get(FIREWALL_CHAIN_DOZABLE)) {
setFirewallChainEnabled(FIREWALL_CHAIN_DOZABLE, true); setFirewallChainEnabled(FIREWALL_CHAIN_DOZABLE, true);
} }
} }
@@ -2013,24 +2010,31 @@ public class NetworkManagementService extends INetworkManagementService.Stub
@Override @Override
public void setFirewallChainEnabled(int chain, boolean enable) { public void setFirewallChainEnabled(int chain, boolean enable) {
enforceSystemUid(); enforceSystemUid();
final String operation = enable ? "enable_chain" : "disable_chain"; synchronized (mQuotaLock) {
try { if (mFirewallChainStates.indexOfKey(chain) >= 0 &&
String chainName; mFirewallChainStates.get(chain) == enable) {
switch(chain) { // All is the same, nothing to do.
case FIREWALL_CHAIN_STANDBY: return;
chainName = FIREWALL_CHAIN_NAME_STANDBY; }
mStandbyChainEnabled = enable; mFirewallChainStates.put(chain, enable);
break;
case FIREWALL_CHAIN_DOZABLE: final String operation = enable ? "enable_chain" : "disable_chain";
chainName = FIREWALL_CHAIN_NAME_DOZABLE; try {
mDozableChainEnabled = enable; String chainName;
break; switch(chain) {
default: case FIREWALL_CHAIN_STANDBY:
throw new IllegalArgumentException("Bad child chain: " + chain); chainName = FIREWALL_CHAIN_NAME_STANDBY;
break;
case FIREWALL_CHAIN_DOZABLE:
chainName = FIREWALL_CHAIN_NAME_DOZABLE;
break;
default:
throw new IllegalArgumentException("Bad child chain: " + chain);
}
mConnector.execute("firewall", operation, chainName);
} catch (NativeDaemonConnectorException e) {
throw e.rethrowAsParcelableException();
} }
mConnector.execute("firewall", operation, chainName);
} catch (NativeDaemonConnectorException e) {
throw e.rethrowAsParcelableException();
} }
} }
@@ -2048,27 +2052,29 @@ public class NetworkManagementService extends INetworkManagementService.Stub
@Override @Override
public void setFirewallUidRules(int chain, int[] uids, int[] rules) { public void setFirewallUidRules(int chain, int[] uids, int[] rules) {
enforceSystemUid(); enforceSystemUid();
SparseIntArray uidFirewallRules = getUidFirewallRules(chain); synchronized (mQuotaLock) {
SparseIntArray newRules = new SparseIntArray(); SparseIntArray uidFirewallRules = getUidFirewallRules(chain);
// apply new set of rules SparseIntArray newRules = new SparseIntArray();
for (int index = uids.length - 1; index >= 0; --index) { // apply new set of rules
int uid = uids[index]; for (int index = uids.length - 1; index >= 0; --index) {
int rule = rules[index]; int uid = uids[index];
setFirewallUidRule(chain, uid, rule); int rule = rules[index];
newRules.put(uid, rule); setFirewallUidRule(chain, uid, rule);
} newRules.put(uid, rule);
// collect the rules to remove. }
SparseIntArray rulesToRemove = new SparseIntArray(); // collect the rules to remove.
for (int index = uidFirewallRules.size() - 1; index >= 0; --index) { SparseIntArray rulesToRemove = new SparseIntArray();
int uid = uidFirewallRules.keyAt(index); for (int index = uidFirewallRules.size() - 1; index >= 0; --index) {
if (newRules.indexOfKey(uid) < 0) { int uid = uidFirewallRules.keyAt(index);
rulesToRemove.put(uid, FIREWALL_RULE_DEFAULT); if (newRules.indexOfKey(uid) < 0) {
rulesToRemove.put(uid, FIREWALL_RULE_DEFAULT);
}
}
// remove dead rules
for (int index = rulesToRemove.size() - 1; index >= 0; --index) {
int uid = rulesToRemove.keyAt(index);
setFirewallUidRuleInternal(chain, uid, FIREWALL_RULE_DEFAULT);
} }
}
// remove dead rules
for (int index = rulesToRemove.size() - 1; index >= 0; --index) {
int uid = rulesToRemove.keyAt(index);
setFirewallUidRuleInternal(chain, uid, FIREWALL_RULE_DEFAULT);
} }
} }
@@ -2094,34 +2100,43 @@ public class NetworkManagementService extends INetworkManagementService.Stub
} }
try { try {
String ruleName; String ruleName = getFirewallRuleName(chain, rule);
if (getFirewallType(chain) == FIREWALL_TYPE_WHITELIST) { String oldRuleName = getFirewallRuleName(chain, oldUidFirewallRule);
if (rule == NetworkPolicyManager.FIREWALL_RULE_ALLOW) {
ruleName = "allow";
} else {
ruleName = "deny";
}
} else { // Blacklist mode
if (rule == NetworkPolicyManager.FIREWALL_RULE_DENY) {
ruleName = "deny";
} else {
ruleName = "allow";
}
}
if (rule == NetworkPolicyManager.FIREWALL_RULE_DEFAULT) { if (rule == NetworkPolicyManager.FIREWALL_RULE_DEFAULT) {
uidFirewallRules.delete(uid); uidFirewallRules.delete(uid);
} else { } else {
uidFirewallRules.put(uid, rule); uidFirewallRules.put(uid, rule);
} }
mConnector.execute("firewall", "set_uid_rule", getFirewallChainName(chain), uid,
ruleName); if (!ruleName.equals(oldRuleName)) {
mConnector.execute("firewall", "set_uid_rule", getFirewallChainName(chain), uid,
ruleName);
}
} catch (NativeDaemonConnectorException e) { } catch (NativeDaemonConnectorException e) {
throw e.rethrowAsParcelableException(); throw e.rethrowAsParcelableException();
} }
} }
} }
private @NonNull String getFirewallRuleName(int chain, int rule) {
String ruleName;
if (getFirewallType(chain) == FIREWALL_TYPE_WHITELIST) {
if (rule == NetworkPolicyManager.FIREWALL_RULE_ALLOW) {
ruleName = "allow";
} else {
ruleName = "deny";
}
} else { // Blacklist mode
if (rule == NetworkPolicyManager.FIREWALL_RULE_DENY) {
ruleName = "deny";
} else {
ruleName = "allow";
}
}
return ruleName;
}
private @NonNull SparseIntArray getUidFirewallRules(int chain) { private @NonNull SparseIntArray getUidFirewallRules(int chain) {
switch (chain) { switch (chain) {
case FIREWALL_CHAIN_STANDBY: case FIREWALL_CHAIN_STANDBY:
@@ -2272,7 +2287,8 @@ public class NetworkManagementService extends INetworkManagementService.Stub
pw.println("]"); pw.println("]");
} }
pw.println("UID firewall standby chain enabled: " + mStandbyChainEnabled); pw.println("UID firewall standby chain enabled: " +
mFirewallChainStates.get(FIREWALL_CHAIN_STANDBY));
synchronized (mUidFirewallStandbyRules) { synchronized (mUidFirewallStandbyRules) {
pw.print("UID firewall standby rule: ["); pw.print("UID firewall standby rule: [");
final int size = mUidFirewallStandbyRules.size(); final int size = mUidFirewallStandbyRules.size();
@@ -2285,7 +2301,8 @@ public class NetworkManagementService extends INetworkManagementService.Stub
pw.println("]"); pw.println("]");
} }
pw.println("UID firewall dozable chain enabled: " + mDozableChainEnabled); pw.println("UID firewall dozable chain enabled: " +
mFirewallChainStates.get(FIREWALL_CHAIN_DOZABLE));
synchronized (mUidFirewallDozableRules) { synchronized (mUidFirewallDozableRules) {
pw.print("UID firewall dozable rule: ["); pw.print("UID firewall dozable rule: [");
final int size = mUidFirewallDozableRules.size(); final int size = mUidFirewallDozableRules.size();

View File

@@ -18,11 +18,6 @@ package com.android.server.content;
import android.app.usage.UsageStatsManagerInternal; import android.app.usage.UsageStatsManagerInternal;
import android.app.usage.UsageStatsManagerInternal.AppIdleStateChangeListener; import android.app.usage.UsageStatsManagerInternal.AppIdleStateChangeListener;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.BatteryManager;
import android.os.UserHandle; import android.os.UserHandle;
import com.android.server.LocalServices; import com.android.server.LocalServices;
@@ -31,53 +26,32 @@ import com.android.server.LocalServices;
* Helper to listen for app idle and charging status changes and restart backed off * Helper to listen for app idle and charging status changes and restart backed off
* sync operations. * sync operations.
*/ */
class AppIdleMonitor implements AppIdleStateChangeListener { class AppIdleMonitor extends AppIdleStateChangeListener {
private final SyncManager mSyncManager; private final SyncManager mSyncManager;
private final UsageStatsManagerInternal mUsageStats; private final UsageStatsManagerInternal mUsageStats;
final BatteryManager mBatteryManager; private boolean mAppIdleParoleOn;
/** Is the device currently plugged into power. */
private boolean mPluggedIn;
private final BroadcastReceiver mReceiver = new BroadcastReceiver() { AppIdleMonitor(SyncManager syncManager) {
@Override
public void onReceive(Context context, Intent intent) {
onPluggedIn(mBatteryManager.isCharging());
}
};
AppIdleMonitor(SyncManager syncManager, Context context) {
mSyncManager = syncManager; mSyncManager = syncManager;
mUsageStats = LocalServices.getService(UsageStatsManagerInternal.class); mUsageStats = LocalServices.getService(UsageStatsManagerInternal.class);
mAppIdleParoleOn = mUsageStats.isAppIdleParoleOn();
mUsageStats.addAppIdleStateChangeListener(this); mUsageStats.addAppIdleStateChangeListener(this);
mBatteryManager = context.getSystemService(BatteryManager.class);
mPluggedIn = isPowered();
registerReceivers(context);
} }
private void registerReceivers(Context context) { void setAppIdleParoleOn(boolean appIdleParoleOn) {
// Monitor battery charging state if (mAppIdleParoleOn == appIdleParoleOn) {
IntentFilter filter = new IntentFilter(BatteryManager.ACTION_CHARGING);
filter.addAction(BatteryManager.ACTION_DISCHARGING);
context.registerReceiver(mReceiver, filter);
}
private boolean isPowered() {
return mBatteryManager.isCharging();
}
void onPluggedIn(boolean pluggedIn) {
if (mPluggedIn == pluggedIn) {
return; return;
} }
mPluggedIn = pluggedIn; mAppIdleParoleOn = appIdleParoleOn;
if (mPluggedIn) { if (mAppIdleParoleOn) {
mSyncManager.onAppNotIdle(null, UserHandle.USER_ALL); mSyncManager.onAppNotIdle(null, UserHandle.USER_ALL);
} }
} }
boolean isAppIdle(String packageName, int userId) { boolean isAppIdle(String packageName, int userId) {
return !mPluggedIn && mUsageStats.isAppIdle(packageName, userId); return !mAppIdleParoleOn && mUsageStats.isAppIdle(packageName, userId);
} }
@Override @Override
@@ -86,4 +60,9 @@ class AppIdleMonitor implements AppIdleStateChangeListener {
if (idle) return; if (idle) return;
mSyncManager.onAppNotIdle(packageName, userId); mSyncManager.onAppNotIdle(packageName, userId);
} }
@Override
public void onParoleStateChanged(boolean isParoleOn) {
setAppIdleParoleOn(isParoleOn);
}
} }

View File

@@ -19,6 +19,7 @@ package com.android.server.content;
import android.accounts.Account; import android.accounts.Account;
import android.accounts.AccountAndUser; import android.accounts.AccountAndUser;
import android.accounts.AccountManager; import android.accounts.AccountManager;
import android.annotation.Nullable;
import android.app.ActivityManager; import android.app.ActivityManager;
import android.app.AlarmManager; import android.app.AlarmManager;
import android.app.AppGlobals; import android.app.AppGlobals;
@@ -461,7 +462,7 @@ public class SyncManager {
mSyncAlarmIntent = PendingIntent.getBroadcast( mSyncAlarmIntent = PendingIntent.getBroadcast(
mContext, 0 /* ignored */, new Intent(ACTION_SYNC_ALARM), 0); mContext, 0 /* ignored */, new Intent(ACTION_SYNC_ALARM), 0);
mAppIdleMonitor = new AppIdleMonitor(this, mContext); mAppIdleMonitor = new AppIdleMonitor(this);
IntentFilter intentFilter = new IntentFilter(ConnectivityManager.CONNECTIVITY_ACTION); IntentFilter intentFilter = new IntentFilter(ConnectivityManager.CONNECTIVITY_ACTION);
context.registerReceiver(mConnectivityIntentReceiver, intentFilter); context.registerReceiver(mConnectivityIntentReceiver, intentFilter);
@@ -1271,7 +1272,7 @@ public class SyncManager {
* @param userId The user for which the package has become active. Can be USER_ALL if * @param userId The user for which the package has become active. Can be USER_ALL if
* the device just plugged in. * the device just plugged in.
*/ */
void onAppNotIdle(String packageName, int userId) { void onAppNotIdle(@Nullable String packageName, int userId) {
synchronized (mSyncQueue) { synchronized (mSyncQueue) {
// For all sync operations in sync queue, if marked as idle, compare with package name // For all sync operations in sync queue, if marked as idle, compare with package name
// and unmark. And clear backoff for the operation. // and unmark. And clear backoff for the operation.

View File

@@ -17,12 +17,7 @@
package com.android.server.job.controllers; package com.android.server.job.controllers;
import android.app.usage.UsageStatsManagerInternal; import android.app.usage.UsageStatsManagerInternal;
import android.content.BroadcastReceiver;
import android.content.Context; import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.BatteryManager;
import android.os.BatteryManagerInternal;
import android.util.Slog; import android.util.Slog;
import com.android.server.LocalServices; import com.android.server.LocalServices;
@@ -38,8 +33,7 @@ import java.util.ArrayList;
* for a certain amount of time (maybe hours or days) are considered idle. When the app comes * for a certain amount of time (maybe hours or days) are considered idle. When the app comes
* out of idle state, it will be allowed to run scheduled jobs. * out of idle state, it will be allowed to run scheduled jobs.
*/ */
public class AppIdleController extends StateController public class AppIdleController extends StateController {
implements UsageStatsManagerInternal.AppIdleStateChangeListener {
private static final String LOG_TAG = "AppIdleController"; private static final String LOG_TAG = "AppIdleController";
private static final boolean DEBUG = false; private static final boolean DEBUG = false;
@@ -49,14 +43,7 @@ public class AppIdleController extends StateController
private static volatile AppIdleController sController; private static volatile AppIdleController sController;
final ArrayList<JobStatus> mTrackedTasks = new ArrayList<JobStatus>(); final ArrayList<JobStatus> mTrackedTasks = new ArrayList<JobStatus>();
private final UsageStatsManagerInternal mUsageStatsInternal; private final UsageStatsManagerInternal mUsageStatsInternal;
private final BatteryManager mBatteryManager; boolean mAppIdleParoleOn;
private boolean mPluggedIn;
private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
@Override public void onReceive(Context context, Intent intent) {
onPluggedIn(mBatteryManager.isCharging());
}
};
public static AppIdleController get(JobSchedulerService service) { public static AppIdleController get(JobSchedulerService service) {
synchronized (sCreationLock) { synchronized (sCreationLock) {
@@ -70,17 +57,8 @@ public class AppIdleController extends StateController
private AppIdleController(StateChangedListener stateChangedListener, Context context) { private AppIdleController(StateChangedListener stateChangedListener, Context context) {
super(stateChangedListener, context); super(stateChangedListener, context);
mUsageStatsInternal = LocalServices.getService(UsageStatsManagerInternal.class); mUsageStatsInternal = LocalServices.getService(UsageStatsManagerInternal.class);
mBatteryManager = context.getSystemService(BatteryManager.class); mAppIdleParoleOn = mUsageStatsInternal.isAppIdleParoleOn();
mPluggedIn = mBatteryManager.isCharging(); mUsageStatsInternal.addAppIdleStateChangeListener(new AppIdleStateChangeListener());
mUsageStatsInternal.addAppIdleStateChangeListener(this);
registerReceivers();
}
private void registerReceivers() {
// Monitor battery charging state
IntentFilter filter = new IntentFilter(BatteryManager.ACTION_CHARGING);
filter.addAction(BatteryManager.ACTION_DISCHARGING);
mContext.registerReceiver(mReceiver, filter);
} }
@Override @Override
@@ -88,7 +66,7 @@ public class AppIdleController extends StateController
synchronized (mTrackedTasks) { synchronized (mTrackedTasks) {
mTrackedTasks.add(jobStatus); mTrackedTasks.add(jobStatus);
String packageName = jobStatus.job.getService().getPackageName(); String packageName = jobStatus.job.getService().getPackageName();
final boolean appIdle = !mPluggedIn && mUsageStatsInternal.isAppIdle(packageName, final boolean appIdle = !mAppIdleParoleOn && mUsageStatsInternal.isAppIdle(packageName,
jobStatus.getUserId()); jobStatus.getUserId());
if (DEBUG) { if (DEBUG) {
Slog.d(LOG_TAG, "Start tracking, setting idle state of " Slog.d(LOG_TAG, "Start tracking, setting idle state of "
@@ -108,7 +86,7 @@ public class AppIdleController extends StateController
@Override @Override
public void dumpControllerState(PrintWriter pw) { public void dumpControllerState(PrintWriter pw) {
pw.println("AppIdle"); pw.println("AppIdle");
pw.println("Plugged In: " + mPluggedIn); pw.println("Parole On: " + mAppIdleParoleOn);
synchronized (mTrackedTasks) { synchronized (mTrackedTasks) {
for (JobStatus task : mTrackedTasks) { for (JobStatus task : mTrackedTasks) {
pw.print(task.job.getService().getPackageName()); pw.print(task.job.getService().getPackageName());
@@ -119,48 +97,20 @@ public class AppIdleController extends StateController
} }
} }
@Override void setAppIdleParoleOn(boolean isAppIdleParoleOn) {
public void onAppIdleStateChanged(String packageName, int userId, boolean idle) {
boolean changed = false;
synchronized (mTrackedTasks) {
// If currently plugged in, we don't care about app idle state
if (mPluggedIn) {
return;
}
for (JobStatus task : mTrackedTasks) {
if (task.job.getService().getPackageName().equals(packageName)
&& task.getUserId() == userId) {
if (task.appNotIdleConstraintSatisfied.get() != !idle) {
if (DEBUG) {
Slog.d(LOG_TAG, "App Idle state changed, setting idle state of "
+ packageName + " to " + idle);
}
task.appNotIdleConstraintSatisfied.set(!idle);
changed = true;
}
}
}
}
if (changed) {
mStateChangedListener.onControllerStateChanged();
}
}
void onPluggedIn(boolean pluggedIn) {
// Flag if any app's idle state has changed // Flag if any app's idle state has changed
boolean changed = false; boolean changed = false;
synchronized (mTrackedTasks) { synchronized (mTrackedTasks) {
if (mPluggedIn == pluggedIn) { if (mAppIdleParoleOn == isAppIdleParoleOn) {
return; return;
} }
mPluggedIn = pluggedIn; mAppIdleParoleOn = isAppIdleParoleOn;
for (JobStatus task : mTrackedTasks) { for (JobStatus task : mTrackedTasks) {
String packageName = task.job.getService().getPackageName(); String packageName = task.job.getService().getPackageName();
final boolean appIdle = !mPluggedIn && mUsageStatsInternal.isAppIdle(packageName, final boolean appIdle = !mAppIdleParoleOn && mUsageStatsInternal.isAppIdle(packageName,
task.getUserId()); task.getUserId());
if (DEBUG) { if (DEBUG) {
Slog.d(LOG_TAG, "Plugged in " + pluggedIn + ", setting idle state of " Slog.d(LOG_TAG, "Setting idle state of " + packageName + " to " + appIdle);
+ packageName + " to " + appIdle);
} }
if (task.appNotIdleConstraintSatisfied.get() == appIdle) { if (task.appNotIdleConstraintSatisfied.get() == appIdle) {
task.appNotIdleConstraintSatisfied.set(!appIdle); task.appNotIdleConstraintSatisfied.set(!appIdle);
@@ -172,4 +122,41 @@ public class AppIdleController extends StateController
mStateChangedListener.onControllerStateChanged(); mStateChangedListener.onControllerStateChanged();
} }
} }
private class AppIdleStateChangeListener
extends UsageStatsManagerInternal.AppIdleStateChangeListener {
@Override
public void onAppIdleStateChanged(String packageName, int userId, boolean idle) {
boolean changed = false;
synchronized (mTrackedTasks) {
if (mAppIdleParoleOn) {
return;
}
for (JobStatus task : mTrackedTasks) {
if (task.job.getService().getPackageName().equals(packageName)
&& task.getUserId() == userId) {
if (task.appNotIdleConstraintSatisfied.get() != !idle) {
if (DEBUG) {
Slog.d(LOG_TAG, "App Idle state changed, setting idle state of "
+ packageName + " to " + idle);
}
task.appNotIdleConstraintSatisfied.set(!idle);
changed = true;
}
}
}
}
if (changed) {
mStateChangedListener.onControllerStateChanged();
}
}
@Override
public void onParoleStateChanged(boolean isParoleOn) {
if (DEBUG) {
Slog.d(LOG_TAG, "Parole on: " + isParoleOn);
}
setAppIdleParoleOn(isParoleOn);
}
}
} }

View File

@@ -86,7 +86,6 @@ import android.app.IUidObserver;
import android.app.Notification; import android.app.Notification;
import android.app.PendingIntent; import android.app.PendingIntent;
import android.app.usage.UsageStatsManagerInternal; import android.app.usage.UsageStatsManagerInternal;
import android.app.usage.UsageStatsManagerInternal.AppIdleStateChangeListener;
import android.content.BroadcastReceiver; import android.content.BroadcastReceiver;
import android.content.ComponentName; import android.content.ComponentName;
import android.content.Context; import android.content.Context;
@@ -154,7 +153,6 @@ import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.util.ArrayUtils; import com.android.internal.util.ArrayUtils;
import com.android.internal.util.FastXmlSerializer; import com.android.internal.util.FastXmlSerializer;
import com.android.internal.util.IndentingPrintWriter; import com.android.internal.util.IndentingPrintWriter;
import com.android.server.DeviceIdleController;
import com.android.server.LocalServices; import com.android.server.LocalServices;
import com.google.android.collect.Lists; import com.google.android.collect.Lists;
@@ -182,8 +180,7 @@ import java.util.List;
* and delivers to listeners, such as {@link ConnectivityManager}, for * and delivers to listeners, such as {@link ConnectivityManager}, for
* enforcement. * enforcement.
*/ */
public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
implements AppIdleStateChangeListener {
private static final String TAG = "NetworkPolicy"; private static final String TAG = "NetworkPolicy";
private static final boolean LOGD = false; private static final boolean LOGD = false;
private static final boolean LOGV = false; private static final boolean LOGV = false;
@@ -279,6 +276,7 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub
final SparseIntArray mUidPolicy = new SparseIntArray(); final SparseIntArray mUidPolicy = new SparseIntArray();
/** Currently derived rules for each UID. */ /** Currently derived rules for each UID. */
final SparseIntArray mUidRules = new SparseIntArray(); final SparseIntArray mUidRules = new SparseIntArray();
/** Set of states for the child firewall chains. True if the chain is active. */
final SparseBooleanArray mFirewallChainStates = new SparseBooleanArray(); final SparseBooleanArray mFirewallChainStates = new SparseBooleanArray();
/** /**
@@ -508,7 +506,7 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub
WifiManager.NETWORK_STATE_CHANGED_ACTION); WifiManager.NETWORK_STATE_CHANGED_ACTION);
mContext.registerReceiver(mWifiStateReceiver, wifiStateFilter, null, mHandler); mContext.registerReceiver(mWifiStateReceiver, wifiStateFilter, null, mHandler);
mUsageStats.addAppIdleStateChangeListener(this); mUsageStats.addAppIdleStateChangeListener(new AppIdleStateChangeListener());
} }
@@ -2043,7 +2041,12 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub
} }
setUidFirewallRules(FIREWALL_CHAIN_DOZABLE, uidRules); setUidFirewallRules(FIREWALL_CHAIN_DOZABLE, uidRules);
} }
enableFirewallChain(FIREWALL_CHAIN_DOZABLE, mDeviceIdleMode); enableFirewallChainLocked(FIREWALL_CHAIN_DOZABLE, mDeviceIdleMode);
}
void updateRulesForAppIdleParoleLocked() {
boolean enableChain = !mUsageStats.isAppIdleParoleOn();
enableFirewallChainLocked(FIREWALL_CHAIN_STANDBY, enableChain);
} }
/** /**
@@ -2187,9 +2190,9 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub
final boolean firewallReject = (uidRules & RULE_REJECT_ALL) != 0; final boolean firewallReject = (uidRules & RULE_REJECT_ALL) != 0;
if (oldFirewallReject != firewallReject) { if (oldFirewallReject != firewallReject) {
setUidFirewallRule(FIREWALL_CHAIN_STANDBY, uid, firewallReject); setUidFirewallRule(FIREWALL_CHAIN_STANDBY, uid, firewallReject);
if (mDeviceIdleMode && !firewallReject) { if (mFirewallChainStates.get(FIREWALL_CHAIN_DOZABLE) && !firewallReject) {
// if we are in device idle mode, and we decide to allow this uid. we need to punch // if the dozable chain is on, and we decide to allow this uid. we need to punch
// a hole in the device idle chain. // a hole in the dozable chain.
setUidFirewallRule(FIREWALL_CHAIN_DOZABLE, uid, false); setUidFirewallRule(FIREWALL_CHAIN_DOZABLE, uid, false);
} }
} }
@@ -2207,15 +2210,25 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub
} }
} }
@Override private class AppIdleStateChangeListener
public void onAppIdleStateChanged(String packageName, int userId, boolean idle) { extends UsageStatsManagerInternal.AppIdleStateChangeListener {
try {
int uid = mContext.getPackageManager().getPackageUid(packageName, userId); @Override
synchronized (mRulesLock) { public void onAppIdleStateChanged(String packageName, int userId, boolean idle) {
updateRulesForUidLocked(uid); try {
int uid = mContext.getPackageManager().getPackageUid(packageName, userId);
synchronized (mRulesLock) {
updateRulesForUidLocked(uid);
}
} catch (NameNotFoundException nnfe) {
}
}
@Override
public void onParoleStateChanged(boolean isParoleOn) {
synchronized (mRulesLock) {
updateRulesForAppIdleParoleLocked();
} }
} catch (NameNotFoundException nnfe) {
return;
} }
} }
@@ -2381,12 +2394,13 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub
/** /**
* Add or remove a uid to the firewall blacklist for all network ifaces. * Add or remove a uid to the firewall blacklist for all network ifaces.
*/ */
private void enableFirewallChain(int chain, boolean enable) { private void enableFirewallChainLocked(int chain, boolean enable) {
if (mFirewallChainStates.indexOfKey(chain) >= 0 && if (mFirewallChainStates.indexOfKey(chain) >= 0 &&
mFirewallChainStates.get(chain) == enable) { mFirewallChainStates.get(chain) == enable) {
// All is the same, nothing to do. // All is the same, nothing to do.
return; return;
} }
mFirewallChainStates.put(chain, enable);
try { try {
mNetworkManager.setFirewallChainEnabled(chain, enable); mNetworkManager.setFirewallChainEnabled(chain, enable);
} catch (IllegalStateException e) { } catch (IllegalStateException e) {

View File

@@ -119,6 +119,7 @@ public class UsageStatsService extends SystemService implements
static final int MSG_CHECK_PAROLE_TIMEOUT = 6; static final int MSG_CHECK_PAROLE_TIMEOUT = 6;
static final int MSG_PAROLE_END_TIMEOUT = 7; static final int MSG_PAROLE_END_TIMEOUT = 7;
static final int MSG_REPORT_CONTENT_PROVIDER_USAGE = 8; static final int MSG_REPORT_CONTENT_PROVIDER_USAGE = 8;
static final int MSG_PAROLE_STATE_CHANGED = 9;
private final Object mLock = new Object(); private final Object mLock = new Object();
Handler mHandler; Handler mHandler;
@@ -313,7 +314,7 @@ public class UsageStatsService extends SystemService implements
mLastAppIdleParoledTime = checkAndGetTimeLocked(); mLastAppIdleParoledTime = checkAndGetTimeLocked();
postNextParoleTimeout(); postNextParoleTimeout();
} }
postCheckIdleStates(UserHandle.USER_ALL); postParoleStateChanged();
} }
} }
} }
@@ -338,6 +339,12 @@ public class UsageStatsService extends SystemService implements
mHandler.sendEmptyMessageDelayed(MSG_PAROLE_END_TIMEOUT, mAppIdleParoleDurationMillis); mHandler.sendEmptyMessageDelayed(MSG_PAROLE_END_TIMEOUT, mAppIdleParoleDurationMillis);
} }
private void postParoleStateChanged() {
if (DEBUG) Slog.d(TAG, "Posting MSG_PAROLE_STATE_CHANGED");
mHandler.removeMessages(MSG_PAROLE_STATE_CHANGED);
mHandler.sendEmptyMessage(MSG_PAROLE_STATE_CHANGED);
}
void postCheckIdleStates(int userId) { void postCheckIdleStates(int userId) {
mHandler.sendMessage(mHandler.obtainMessage(MSG_CHECK_IDLE_STATES, userId, 0)); mHandler.sendMessage(mHandler.obtainMessage(MSG_CHECK_IDLE_STATES, userId, 0));
} }
@@ -756,6 +763,13 @@ public class UsageStatsService extends SystemService implements
} }
} }
boolean isAppIdleFilteredOrParoled(String packageName, int userId, long timeNow) {
if (mAppIdleParoled) {
return false;
}
return isAppIdleFiltered(packageName, userId, timeNow);
}
boolean isAppIdleFiltered(String packageName, int userId, long timeNow) { boolean isAppIdleFiltered(String packageName, int userId, long timeNow) {
final UserUsageStatsService userService; final UserUsageStatsService userService;
final long screenOnTime; final long screenOnTime;
@@ -782,13 +796,6 @@ public class UsageStatsService extends SystemService implements
if (!mAppIdleEnabled) { if (!mAppIdleEnabled) {
return false; 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 (packageName.equals("android")) return false; if (packageName.equals("android")) return false;
try { try {
if (mDeviceIdleController.isPowerSaveWhitelistApp(packageName)) { if (mDeviceIdleController.isPowerSaveWhitelistApp(packageName)) {
@@ -846,6 +853,12 @@ public class UsageStatsService extends SystemService implements
} }
} }
void informParoleStateChanged() {
for (AppIdleStateChangeListener listener : mPackageAccessListeners) {
listener.onParoleStateChanged(mAppIdleParoled);
}
}
private static boolean validRange(long currentTime, long beginTime, long endTime) { private static boolean validRange(long currentTime, long beginTime, long endTime) {
return beginTime <= currentTime && beginTime < endTime; return beginTime <= currentTime && beginTime < endTime;
} }
@@ -975,6 +988,11 @@ public class UsageStatsService extends SystemService implements
args.recycle(); args.recycle();
break; break;
case MSG_PAROLE_STATE_CHANGED:
if (DEBUG) Slog.d(TAG, "Parole state changed: " + mAppIdleParoled);
informParoleStateChanged();
break;
default: default:
super.handleMessage(msg); super.handleMessage(msg);
break; break;
@@ -1126,7 +1144,7 @@ public class UsageStatsService extends SystemService implements
} }
final long token = Binder.clearCallingIdentity(); final long token = Binder.clearCallingIdentity();
try { try {
return UsageStatsService.this.isAppIdleFiltered(packageName, userId, -1); return UsageStatsService.this.isAppIdleFilteredOrParoled(packageName, userId, -1);
} finally { } finally {
Binder.restoreCallingIdentity(token); Binder.restoreCallingIdentity(token);
} }
@@ -1250,6 +1268,11 @@ public class UsageStatsService extends SystemService implements
return UsageStatsService.this.isAppIdleFiltered(packageName, userId, -1); return UsageStatsService.this.isAppIdleFiltered(packageName, userId, -1);
} }
@Override
public boolean isAppIdleParoleOn() {
return mAppIdleParoled;
}
@Override @Override
public void prepareShutdown() { public void prepareShutdown() {
// This method *WILL* do IO work, but we must block until it is finished or else // This method *WILL* do IO work, but we must block until it is finished or else
@@ -1261,6 +1284,7 @@ public class UsageStatsService extends SystemService implements
@Override @Override
public void addAppIdleStateChangeListener(AppIdleStateChangeListener listener) { public void addAppIdleStateChangeListener(AppIdleStateChangeListener listener) {
UsageStatsService.this.addListener(listener); UsageStatsService.this.addListener(listener);
listener.onParoleStateChanged(isAppIdleParoleOn());
} }
@Override @Override