am a2c159fe: Merge "system_server: optimize app idle parole state change" into mnc-dev
* commit 'a2c159fede892a54b9b98e681c6a3053ab4dbf31': system_server: optimize app idle parole state change
This commit is contained in:
@@ -76,6 +76,12 @@ public abstract class UsageStatsManagerInternal {
|
||||
*/
|
||||
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.
|
||||
* @param listener A listener within the system process.
|
||||
@@ -90,8 +96,9 @@ public abstract class UsageStatsManagerInternal {
|
||||
public abstract void removeAppIdleStateChangeListener(
|
||||
AppIdleStateChangeListener listener);
|
||||
|
||||
public interface AppIdleStateChangeListener {
|
||||
void onAppIdleStateChanged(String packageName, int userId, boolean idle);
|
||||
public static abstract class AppIdleStateChangeListener {
|
||||
public abstract void onAppIdleStateChanged(String packageName, int userId, boolean idle);
|
||||
public abstract void onParoleStateChanged(boolean isParoleOn);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -214,9 +214,9 @@ public class NetworkManagementService extends INetworkManagementService.Stub
|
||||
*/
|
||||
@GuardedBy("mQuotaLock")
|
||||
private SparseIntArray mUidFirewallDozableRules = new SparseIntArray();
|
||||
|
||||
private boolean mStandbyChainEnabled = false;
|
||||
private boolean mDozableChainEnabled = false;
|
||||
/** Set of states for the child firewall chains. True if the chain is active. */
|
||||
@GuardedBy("mQuotaLock")
|
||||
final SparseBooleanArray mFirewallChainStates = new SparseBooleanArray();
|
||||
|
||||
private Object mIdleTimerLock = new Object();
|
||||
/** Set of interfaces with active idle timers. */
|
||||
@@ -307,9 +307,6 @@ public class NetworkManagementService extends INetworkManagementService.Stub
|
||||
}
|
||||
|
||||
public void systemReady() {
|
||||
// init firewall states
|
||||
mDozableChainEnabled = false;
|
||||
mStandbyChainEnabled = true;
|
||||
prepareNativeDaemon();
|
||||
if (DBG) Slog.d(TAG, "Prepared");
|
||||
}
|
||||
@@ -611,7 +608,7 @@ public class NetworkManagementService extends INetworkManagementService.Stub
|
||||
uidFirewallRules.valueAt(i));
|
||||
}
|
||||
}
|
||||
if (mStandbyChainEnabled) {
|
||||
if (mFirewallChainStates.get(FIREWALL_CHAIN_STANDBY)) {
|
||||
setFirewallChainEnabled(FIREWALL_CHAIN_STANDBY, true);
|
||||
}
|
||||
|
||||
@@ -625,7 +622,7 @@ public class NetworkManagementService extends INetworkManagementService.Stub
|
||||
uidFirewallRules.valueAt(i));
|
||||
}
|
||||
}
|
||||
if (mDozableChainEnabled) {
|
||||
if (mFirewallChainStates.get(FIREWALL_CHAIN_DOZABLE)) {
|
||||
setFirewallChainEnabled(FIREWALL_CHAIN_DOZABLE, true);
|
||||
}
|
||||
}
|
||||
@@ -2013,24 +2010,31 @@ public class NetworkManagementService extends INetworkManagementService.Stub
|
||||
@Override
|
||||
public void setFirewallChainEnabled(int chain, boolean enable) {
|
||||
enforceSystemUid();
|
||||
final String operation = enable ? "enable_chain" : "disable_chain";
|
||||
try {
|
||||
String chainName;
|
||||
switch(chain) {
|
||||
case FIREWALL_CHAIN_STANDBY:
|
||||
chainName = FIREWALL_CHAIN_NAME_STANDBY;
|
||||
mStandbyChainEnabled = enable;
|
||||
break;
|
||||
case FIREWALL_CHAIN_DOZABLE:
|
||||
chainName = FIREWALL_CHAIN_NAME_DOZABLE;
|
||||
mDozableChainEnabled = enable;
|
||||
break;
|
||||
default:
|
||||
throw new IllegalArgumentException("Bad child chain: " + chain);
|
||||
synchronized (mQuotaLock) {
|
||||
if (mFirewallChainStates.indexOfKey(chain) >= 0 &&
|
||||
mFirewallChainStates.get(chain) == enable) {
|
||||
// All is the same, nothing to do.
|
||||
return;
|
||||
}
|
||||
mFirewallChainStates.put(chain, enable);
|
||||
|
||||
final String operation = enable ? "enable_chain" : "disable_chain";
|
||||
try {
|
||||
String chainName;
|
||||
switch(chain) {
|
||||
case FIREWALL_CHAIN_STANDBY:
|
||||
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
|
||||
public void setFirewallUidRules(int chain, int[] uids, int[] rules) {
|
||||
enforceSystemUid();
|
||||
SparseIntArray uidFirewallRules = getUidFirewallRules(chain);
|
||||
SparseIntArray newRules = new SparseIntArray();
|
||||
// apply new set of rules
|
||||
for (int index = uids.length - 1; index >= 0; --index) {
|
||||
int uid = uids[index];
|
||||
int rule = rules[index];
|
||||
setFirewallUidRule(chain, uid, rule);
|
||||
newRules.put(uid, rule);
|
||||
}
|
||||
// collect the rules to remove.
|
||||
SparseIntArray rulesToRemove = new SparseIntArray();
|
||||
for (int index = uidFirewallRules.size() - 1; index >= 0; --index) {
|
||||
int uid = uidFirewallRules.keyAt(index);
|
||||
if (newRules.indexOfKey(uid) < 0) {
|
||||
rulesToRemove.put(uid, FIREWALL_RULE_DEFAULT);
|
||||
synchronized (mQuotaLock) {
|
||||
SparseIntArray uidFirewallRules = getUidFirewallRules(chain);
|
||||
SparseIntArray newRules = new SparseIntArray();
|
||||
// apply new set of rules
|
||||
for (int index = uids.length - 1; index >= 0; --index) {
|
||||
int uid = uids[index];
|
||||
int rule = rules[index];
|
||||
setFirewallUidRule(chain, uid, rule);
|
||||
newRules.put(uid, rule);
|
||||
}
|
||||
// collect the rules to remove.
|
||||
SparseIntArray rulesToRemove = new SparseIntArray();
|
||||
for (int index = uidFirewallRules.size() - 1; index >= 0; --index) {
|
||||
int uid = uidFirewallRules.keyAt(index);
|
||||
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 {
|
||||
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";
|
||||
}
|
||||
}
|
||||
String ruleName = getFirewallRuleName(chain, rule);
|
||||
String oldRuleName = getFirewallRuleName(chain, oldUidFirewallRule);
|
||||
|
||||
if (rule == NetworkPolicyManager.FIREWALL_RULE_DEFAULT) {
|
||||
uidFirewallRules.delete(uid);
|
||||
} else {
|
||||
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) {
|
||||
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) {
|
||||
switch (chain) {
|
||||
case FIREWALL_CHAIN_STANDBY:
|
||||
@@ -2272,7 +2287,8 @@ public class NetworkManagementService extends INetworkManagementService.Stub
|
||||
pw.println("]");
|
||||
}
|
||||
|
||||
pw.println("UID firewall standby chain enabled: " + mStandbyChainEnabled);
|
||||
pw.println("UID firewall standby chain enabled: " +
|
||||
mFirewallChainStates.get(FIREWALL_CHAIN_STANDBY));
|
||||
synchronized (mUidFirewallStandbyRules) {
|
||||
pw.print("UID firewall standby rule: [");
|
||||
final int size = mUidFirewallStandbyRules.size();
|
||||
@@ -2285,7 +2301,8 @@ public class NetworkManagementService extends INetworkManagementService.Stub
|
||||
pw.println("]");
|
||||
}
|
||||
|
||||
pw.println("UID firewall dozable chain enabled: " + mDozableChainEnabled);
|
||||
pw.println("UID firewall dozable chain enabled: " +
|
||||
mFirewallChainStates.get(FIREWALL_CHAIN_DOZABLE));
|
||||
synchronized (mUidFirewallDozableRules) {
|
||||
pw.print("UID firewall dozable rule: [");
|
||||
final int size = mUidFirewallDozableRules.size();
|
||||
|
||||
@@ -18,11 +18,6 @@ package com.android.server.content;
|
||||
|
||||
import android.app.usage.UsageStatsManagerInternal;
|
||||
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 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
|
||||
* sync operations.
|
||||
*/
|
||||
class AppIdleMonitor implements AppIdleStateChangeListener {
|
||||
class AppIdleMonitor extends AppIdleStateChangeListener {
|
||||
|
||||
private final SyncManager mSyncManager;
|
||||
private final UsageStatsManagerInternal mUsageStats;
|
||||
final BatteryManager mBatteryManager;
|
||||
/** Is the device currently plugged into power. */
|
||||
private boolean mPluggedIn;
|
||||
private boolean mAppIdleParoleOn;
|
||||
|
||||
private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
|
||||
@Override
|
||||
public void onReceive(Context context, Intent intent) {
|
||||
onPluggedIn(mBatteryManager.isCharging());
|
||||
}
|
||||
};
|
||||
|
||||
AppIdleMonitor(SyncManager syncManager, Context context) {
|
||||
AppIdleMonitor(SyncManager syncManager) {
|
||||
mSyncManager = syncManager;
|
||||
mUsageStats = LocalServices.getService(UsageStatsManagerInternal.class);
|
||||
mAppIdleParoleOn = mUsageStats.isAppIdleParoleOn();
|
||||
|
||||
mUsageStats.addAppIdleStateChangeListener(this);
|
||||
mBatteryManager = context.getSystemService(BatteryManager.class);
|
||||
mPluggedIn = isPowered();
|
||||
registerReceivers(context);
|
||||
}
|
||||
|
||||
private void registerReceivers(Context context) {
|
||||
// Monitor battery charging state
|
||||
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) {
|
||||
void setAppIdleParoleOn(boolean appIdleParoleOn) {
|
||||
if (mAppIdleParoleOn == appIdleParoleOn) {
|
||||
return;
|
||||
}
|
||||
mPluggedIn = pluggedIn;
|
||||
if (mPluggedIn) {
|
||||
mAppIdleParoleOn = appIdleParoleOn;
|
||||
if (mAppIdleParoleOn) {
|
||||
mSyncManager.onAppNotIdle(null, UserHandle.USER_ALL);
|
||||
}
|
||||
}
|
||||
|
||||
boolean isAppIdle(String packageName, int userId) {
|
||||
return !mPluggedIn && mUsageStats.isAppIdle(packageName, userId);
|
||||
return !mAppIdleParoleOn && mUsageStats.isAppIdle(packageName, userId);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -86,4 +60,9 @@ class AppIdleMonitor implements AppIdleStateChangeListener {
|
||||
if (idle) return;
|
||||
mSyncManager.onAppNotIdle(packageName, userId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onParoleStateChanged(boolean isParoleOn) {
|
||||
setAppIdleParoleOn(isParoleOn);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,6 +19,7 @@ package com.android.server.content;
|
||||
import android.accounts.Account;
|
||||
import android.accounts.AccountAndUser;
|
||||
import android.accounts.AccountManager;
|
||||
import android.annotation.Nullable;
|
||||
import android.app.ActivityManager;
|
||||
import android.app.AlarmManager;
|
||||
import android.app.AppGlobals;
|
||||
@@ -461,7 +462,7 @@ public class SyncManager {
|
||||
mSyncAlarmIntent = PendingIntent.getBroadcast(
|
||||
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);
|
||||
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
|
||||
* the device just plugged in.
|
||||
*/
|
||||
void onAppNotIdle(String packageName, int userId) {
|
||||
void onAppNotIdle(@Nullable String packageName, int userId) {
|
||||
synchronized (mSyncQueue) {
|
||||
// For all sync operations in sync queue, if marked as idle, compare with package name
|
||||
// and unmark. And clear backoff for the operation.
|
||||
|
||||
@@ -17,12 +17,7 @@
|
||||
package com.android.server.job.controllers;
|
||||
|
||||
import android.app.usage.UsageStatsManagerInternal;
|
||||
import android.content.BroadcastReceiver;
|
||||
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 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
|
||||
* out of idle state, it will be allowed to run scheduled jobs.
|
||||
*/
|
||||
public class AppIdleController extends StateController
|
||||
implements UsageStatsManagerInternal.AppIdleStateChangeListener {
|
||||
public class AppIdleController extends StateController {
|
||||
|
||||
private static final String LOG_TAG = "AppIdleController";
|
||||
private static final boolean DEBUG = false;
|
||||
@@ -49,14 +43,7 @@ public class AppIdleController extends StateController
|
||||
private static volatile AppIdleController sController;
|
||||
final ArrayList<JobStatus> mTrackedTasks = new ArrayList<JobStatus>();
|
||||
private final UsageStatsManagerInternal mUsageStatsInternal;
|
||||
private final BatteryManager mBatteryManager;
|
||||
private boolean mPluggedIn;
|
||||
|
||||
private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
|
||||
@Override public void onReceive(Context context, Intent intent) {
|
||||
onPluggedIn(mBatteryManager.isCharging());
|
||||
}
|
||||
};
|
||||
boolean mAppIdleParoleOn;
|
||||
|
||||
public static AppIdleController get(JobSchedulerService service) {
|
||||
synchronized (sCreationLock) {
|
||||
@@ -70,17 +57,8 @@ public class AppIdleController extends StateController
|
||||
private AppIdleController(StateChangedListener stateChangedListener, Context context) {
|
||||
super(stateChangedListener, context);
|
||||
mUsageStatsInternal = LocalServices.getService(UsageStatsManagerInternal.class);
|
||||
mBatteryManager = context.getSystemService(BatteryManager.class);
|
||||
mPluggedIn = mBatteryManager.isCharging();
|
||||
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);
|
||||
mAppIdleParoleOn = mUsageStatsInternal.isAppIdleParoleOn();
|
||||
mUsageStatsInternal.addAppIdleStateChangeListener(new AppIdleStateChangeListener());
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -88,7 +66,7 @@ public class AppIdleController extends StateController
|
||||
synchronized (mTrackedTasks) {
|
||||
mTrackedTasks.add(jobStatus);
|
||||
String packageName = jobStatus.job.getService().getPackageName();
|
||||
final boolean appIdle = !mPluggedIn && mUsageStatsInternal.isAppIdle(packageName,
|
||||
final boolean appIdle = !mAppIdleParoleOn && mUsageStatsInternal.isAppIdle(packageName,
|
||||
jobStatus.getUserId());
|
||||
if (DEBUG) {
|
||||
Slog.d(LOG_TAG, "Start tracking, setting idle state of "
|
||||
@@ -108,7 +86,7 @@ public class AppIdleController extends StateController
|
||||
@Override
|
||||
public void dumpControllerState(PrintWriter pw) {
|
||||
pw.println("AppIdle");
|
||||
pw.println("Plugged In: " + mPluggedIn);
|
||||
pw.println("Parole On: " + mAppIdleParoleOn);
|
||||
synchronized (mTrackedTasks) {
|
||||
for (JobStatus task : mTrackedTasks) {
|
||||
pw.print(task.job.getService().getPackageName());
|
||||
@@ -119,48 +97,20 @@ public class AppIdleController extends StateController
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
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) {
|
||||
void setAppIdleParoleOn(boolean isAppIdleParoleOn) {
|
||||
// Flag if any app's idle state has changed
|
||||
boolean changed = false;
|
||||
synchronized (mTrackedTasks) {
|
||||
if (mPluggedIn == pluggedIn) {
|
||||
if (mAppIdleParoleOn == isAppIdleParoleOn) {
|
||||
return;
|
||||
}
|
||||
mPluggedIn = pluggedIn;
|
||||
mAppIdleParoleOn = isAppIdleParoleOn;
|
||||
for (JobStatus task : mTrackedTasks) {
|
||||
String packageName = task.job.getService().getPackageName();
|
||||
final boolean appIdle = !mPluggedIn && mUsageStatsInternal.isAppIdle(packageName,
|
||||
final boolean appIdle = !mAppIdleParoleOn && mUsageStatsInternal.isAppIdle(packageName,
|
||||
task.getUserId());
|
||||
if (DEBUG) {
|
||||
Slog.d(LOG_TAG, "Plugged in " + pluggedIn + ", setting idle state of "
|
||||
+ packageName + " to " + appIdle);
|
||||
Slog.d(LOG_TAG, "Setting idle state of " + packageName + " to " + appIdle);
|
||||
}
|
||||
if (task.appNotIdleConstraintSatisfied.get() == appIdle) {
|
||||
task.appNotIdleConstraintSatisfied.set(!appIdle);
|
||||
@@ -172,4 +122,41 @@ public class AppIdleController extends StateController
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -86,7 +86,6 @@ import android.app.IUidObserver;
|
||||
import android.app.Notification;
|
||||
import android.app.PendingIntent;
|
||||
import android.app.usage.UsageStatsManagerInternal;
|
||||
import android.app.usage.UsageStatsManagerInternal.AppIdleStateChangeListener;
|
||||
import android.content.BroadcastReceiver;
|
||||
import android.content.ComponentName;
|
||||
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.FastXmlSerializer;
|
||||
import com.android.internal.util.IndentingPrintWriter;
|
||||
import com.android.server.DeviceIdleController;
|
||||
import com.android.server.LocalServices;
|
||||
import com.google.android.collect.Lists;
|
||||
|
||||
@@ -182,8 +180,7 @@ import java.util.List;
|
||||
* and delivers to listeners, such as {@link ConnectivityManager}, for
|
||||
* enforcement.
|
||||
*/
|
||||
public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub
|
||||
implements AppIdleStateChangeListener {
|
||||
public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
|
||||
private static final String TAG = "NetworkPolicy";
|
||||
private static final boolean LOGD = false;
|
||||
private static final boolean LOGV = false;
|
||||
@@ -279,6 +276,7 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub
|
||||
final SparseIntArray mUidPolicy = new SparseIntArray();
|
||||
/** Currently derived rules for each UID. */
|
||||
final SparseIntArray mUidRules = new SparseIntArray();
|
||||
/** Set of states for the child firewall chains. True if the chain is active. */
|
||||
final SparseBooleanArray mFirewallChainStates = new SparseBooleanArray();
|
||||
|
||||
/**
|
||||
@@ -508,7 +506,7 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub
|
||||
WifiManager.NETWORK_STATE_CHANGED_ACTION);
|
||||
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);
|
||||
}
|
||||
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;
|
||||
if (oldFirewallReject != firewallReject) {
|
||||
setUidFirewallRule(FIREWALL_CHAIN_STANDBY, uid, firewallReject);
|
||||
if (mDeviceIdleMode && !firewallReject) {
|
||||
// if we are in device idle mode, and we decide to allow this uid. we need to punch
|
||||
// a hole in the device idle chain.
|
||||
if (mFirewallChainStates.get(FIREWALL_CHAIN_DOZABLE) && !firewallReject) {
|
||||
// if the dozable chain is on, and we decide to allow this uid. we need to punch
|
||||
// a hole in the dozable chain.
|
||||
setUidFirewallRule(FIREWALL_CHAIN_DOZABLE, uid, false);
|
||||
}
|
||||
}
|
||||
@@ -2207,15 +2210,25 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAppIdleStateChanged(String packageName, int userId, boolean idle) {
|
||||
try {
|
||||
int uid = mContext.getPackageManager().getPackageUid(packageName, userId);
|
||||
synchronized (mRulesLock) {
|
||||
updateRulesForUidLocked(uid);
|
||||
private class AppIdleStateChangeListener
|
||||
extends UsageStatsManagerInternal.AppIdleStateChangeListener {
|
||||
|
||||
@Override
|
||||
public void onAppIdleStateChanged(String packageName, int userId, boolean idle) {
|
||||
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.
|
||||
*/
|
||||
private void enableFirewallChain(int chain, boolean enable) {
|
||||
private void enableFirewallChainLocked(int chain, boolean enable) {
|
||||
if (mFirewallChainStates.indexOfKey(chain) >= 0 &&
|
||||
mFirewallChainStates.get(chain) == enable) {
|
||||
// All is the same, nothing to do.
|
||||
return;
|
||||
}
|
||||
mFirewallChainStates.put(chain, enable);
|
||||
try {
|
||||
mNetworkManager.setFirewallChainEnabled(chain, enable);
|
||||
} catch (IllegalStateException e) {
|
||||
|
||||
@@ -119,6 +119,7 @@ public class UsageStatsService extends SystemService implements
|
||||
static final int MSG_CHECK_PAROLE_TIMEOUT = 6;
|
||||
static final int MSG_PAROLE_END_TIMEOUT = 7;
|
||||
static final int MSG_REPORT_CONTENT_PROVIDER_USAGE = 8;
|
||||
static final int MSG_PAROLE_STATE_CHANGED = 9;
|
||||
|
||||
private final Object mLock = new Object();
|
||||
Handler mHandler;
|
||||
@@ -313,7 +314,7 @@ public class UsageStatsService extends SystemService implements
|
||||
mLastAppIdleParoledTime = checkAndGetTimeLocked();
|
||||
postNextParoleTimeout();
|
||||
}
|
||||
postCheckIdleStates(UserHandle.USER_ALL);
|
||||
postParoleStateChanged();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -338,6 +339,12 @@ public class UsageStatsService extends SystemService implements
|
||||
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) {
|
||||
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) {
|
||||
final UserUsageStatsService userService;
|
||||
final long screenOnTime;
|
||||
@@ -782,13 +796,6 @@ public class UsageStatsService extends SystemService implements
|
||||
if (!mAppIdleEnabled) {
|
||||
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;
|
||||
try {
|
||||
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) {
|
||||
return beginTime <= currentTime && beginTime < endTime;
|
||||
}
|
||||
@@ -975,6 +988,11 @@ public class UsageStatsService extends SystemService implements
|
||||
args.recycle();
|
||||
break;
|
||||
|
||||
case MSG_PAROLE_STATE_CHANGED:
|
||||
if (DEBUG) Slog.d(TAG, "Parole state changed: " + mAppIdleParoled);
|
||||
informParoleStateChanged();
|
||||
break;
|
||||
|
||||
default:
|
||||
super.handleMessage(msg);
|
||||
break;
|
||||
@@ -1126,7 +1144,7 @@ public class UsageStatsService extends SystemService implements
|
||||
}
|
||||
final long token = Binder.clearCallingIdentity();
|
||||
try {
|
||||
return UsageStatsService.this.isAppIdleFiltered(packageName, userId, -1);
|
||||
return UsageStatsService.this.isAppIdleFilteredOrParoled(packageName, userId, -1);
|
||||
} finally {
|
||||
Binder.restoreCallingIdentity(token);
|
||||
}
|
||||
@@ -1250,6 +1268,11 @@ public class UsageStatsService extends SystemService implements
|
||||
return UsageStatsService.this.isAppIdleFiltered(packageName, userId, -1);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isAppIdleParoleOn() {
|
||||
return mAppIdleParoled;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void prepareShutdown() {
|
||||
// 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
|
||||
public void addAppIdleStateChangeListener(AppIdleStateChangeListener listener) {
|
||||
UsageStatsService.this.addListener(listener);
|
||||
listener.onParoleStateChanged(isAppIdleParoleOn());
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
Reference in New Issue
Block a user