Merge "Clean up AppStateTracker state on package removed"
This commit is contained in:
committed by
Android (Google) Code Review
commit
31e35a2614
@@ -125,10 +125,11 @@ public class AppStateTrackerImpl implements AppStateTracker {
|
||||
private int[] mTempExemptAppIds = mPowerExemptAllAppIds;
|
||||
|
||||
/**
|
||||
* Per-user packages that are in the EXEMPT bucket.
|
||||
* Per-user packages that are in the EXEMPTED bucket.
|
||||
*/
|
||||
@GuardedBy("mLock")
|
||||
private final SparseSetArray<String> mExemptBucketPackages = new SparseSetArray<>();
|
||||
@VisibleForTesting
|
||||
final SparseSetArray<String> mExemptedBucketPackages = new SparseSetArray<>();
|
||||
|
||||
@GuardedBy("mLock")
|
||||
final ArraySet<Listener> mListeners = new ArraySet<>();
|
||||
@@ -180,7 +181,7 @@ public class AppStateTrackerImpl implements AppStateTracker {
|
||||
int ALL_UNEXEMPTED = 3;
|
||||
int ALL_EXEMPTION_LIST_CHANGED = 4;
|
||||
int TEMP_EXEMPTION_LIST_CHANGED = 5;
|
||||
int EXEMPT_BUCKET_CHANGED = 6;
|
||||
int EXEMPTED_BUCKET_CHANGED = 6;
|
||||
int FORCE_ALL_CHANGED = 7;
|
||||
int FORCE_APP_STANDBY_FEATURE_FLAG_CHANGED = 8;
|
||||
|
||||
@@ -195,7 +196,7 @@ public class AppStateTrackerImpl implements AppStateTracker {
|
||||
"ALL_UNEXEMPTED",
|
||||
"ALL_EXEMPTION_LIST_CHANGED",
|
||||
"TEMP_EXEMPTION_LIST_CHANGED",
|
||||
"EXEMPT_BUCKET_CHANGED",
|
||||
"EXEMPTED_BUCKET_CHANGED",
|
||||
"FORCE_ALL_CHANGED",
|
||||
"FORCE_APP_STANDBY_FEATURE_FLAG_CHANGED",
|
||||
|
||||
@@ -338,9 +339,9 @@ public class AppStateTrackerImpl implements AppStateTracker {
|
||||
}
|
||||
|
||||
/**
|
||||
* This is called when the EXEMPT bucket is updated.
|
||||
* This is called when the EXEMPTED bucket is updated.
|
||||
*/
|
||||
private void onExemptBucketChanged(AppStateTrackerImpl sender) {
|
||||
private void onExemptedBucketChanged(AppStateTrackerImpl sender) {
|
||||
// This doesn't happen very often, so just re-evaluate all jobs / alarms.
|
||||
updateAllJobs();
|
||||
unblockAllUnrestrictedAlarms();
|
||||
@@ -424,6 +425,38 @@ public class AppStateTrackerImpl implements AppStateTracker {
|
||||
mHandler = new MyHandler(looper);
|
||||
}
|
||||
|
||||
private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
|
||||
@Override
|
||||
public void onReceive(Context context, Intent intent) {
|
||||
final int userId = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, -1);
|
||||
switch (intent.getAction()) {
|
||||
case Intent.ACTION_USER_REMOVED:
|
||||
if (userId > 0) {
|
||||
mHandler.doUserRemoved(userId);
|
||||
}
|
||||
break;
|
||||
case Intent.ACTION_BATTERY_CHANGED:
|
||||
synchronized (mLock) {
|
||||
mIsPluggedIn = (intent.getIntExtra(BatteryManager.EXTRA_PLUGGED, 0) != 0);
|
||||
}
|
||||
updateForceAllAppStandbyState();
|
||||
break;
|
||||
case Intent.ACTION_PACKAGE_REMOVED:
|
||||
if (!intent.getBooleanExtra(Intent.EXTRA_REPLACING, false)) {
|
||||
final String pkgName = intent.getData().getSchemeSpecificPart();
|
||||
final int uid = intent.getIntExtra(Intent.EXTRA_UID, -1);
|
||||
// No need to notify for state change as all the alarms and jobs should be
|
||||
// removed too.
|
||||
mExemptedBucketPackages.remove(userId, pkgName);
|
||||
mRunAnyRestrictedPackages.remove(Pair.create(uid, pkgName));
|
||||
mActiveUids.delete(uid);
|
||||
mForegroundUids.delete(uid);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Call it when the system is ready.
|
||||
*/
|
||||
@@ -465,8 +498,11 @@ public class AppStateTrackerImpl implements AppStateTracker {
|
||||
IntentFilter filter = new IntentFilter();
|
||||
filter.addAction(Intent.ACTION_USER_REMOVED);
|
||||
filter.addAction(Intent.ACTION_BATTERY_CHANGED);
|
||||
filter.addAction(Intent.ACTION_PACKAGE_REMOVED);
|
||||
mContext.registerReceiver(new MyReceiver(), filter);
|
||||
mContext.registerReceiver(mReceiver, filter);
|
||||
|
||||
filter = new IntentFilter(Intent.ACTION_PACKAGE_REMOVED);
|
||||
filter.addDataScheme(IntentFilter.SCHEME_PACKAGE);
|
||||
mContext.registerReceiver(mReceiver, filter);
|
||||
|
||||
refreshForcedAppStandbyUidPackagesLocked();
|
||||
|
||||
@@ -693,30 +729,6 @@ public class AppStateTrackerImpl implements AppStateTracker {
|
||||
}
|
||||
}
|
||||
|
||||
private final class MyReceiver extends BroadcastReceiver {
|
||||
@Override
|
||||
public void onReceive(Context context, Intent intent) {
|
||||
if (Intent.ACTION_USER_REMOVED.equals(intent.getAction())) {
|
||||
final int userId = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, -1);
|
||||
if (userId > 0) {
|
||||
mHandler.doUserRemoved(userId);
|
||||
}
|
||||
} else if (Intent.ACTION_BATTERY_CHANGED.equals(intent.getAction())) {
|
||||
synchronized (mLock) {
|
||||
mIsPluggedIn = (intent.getIntExtra(BatteryManager.EXTRA_PLUGGED, 0) != 0);
|
||||
}
|
||||
updateForceAllAppStandbyState();
|
||||
} else if (Intent.ACTION_PACKAGE_REMOVED.equals(intent.getAction())
|
||||
&& !intent.getBooleanExtra(Intent.EXTRA_REPLACING, false)) {
|
||||
final int userId = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, -1);
|
||||
final String pkgName = intent.getData().getSchemeSpecificPart();
|
||||
if (mExemptBucketPackages.remove(userId, pkgName)) {
|
||||
mHandler.notifyExemptBucketChanged();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
final class StandbyTracker extends AppIdleStateChangeListener {
|
||||
@Override
|
||||
public void onAppIdleStateChanged(String packageName, int userId, boolean idle,
|
||||
@@ -728,12 +740,12 @@ public class AppStateTrackerImpl implements AppStateTracker {
|
||||
synchronized (mLock) {
|
||||
final boolean changed;
|
||||
if (bucket == UsageStatsManager.STANDBY_BUCKET_EXEMPTED) {
|
||||
changed = mExemptBucketPackages.add(userId, packageName);
|
||||
changed = mExemptedBucketPackages.add(userId, packageName);
|
||||
} else {
|
||||
changed = mExemptBucketPackages.remove(userId, packageName);
|
||||
changed = mExemptedBucketPackages.remove(userId, packageName);
|
||||
}
|
||||
if (changed) {
|
||||
mHandler.notifyExemptBucketChanged();
|
||||
mHandler.notifyExemptedBucketChanged();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -755,7 +767,7 @@ public class AppStateTrackerImpl implements AppStateTracker {
|
||||
private static final int MSG_FORCE_ALL_CHANGED = 7;
|
||||
private static final int MSG_USER_REMOVED = 8;
|
||||
private static final int MSG_FORCE_APP_STANDBY_FEATURE_FLAG_CHANGED = 9;
|
||||
private static final int MSG_EXEMPT_BUCKET_CHANGED = 10;
|
||||
private static final int MSG_EXEMPTED_BUCKET_CHANGED = 10;
|
||||
|
||||
private static final int MSG_ON_UID_STATE_CHANGED = 11;
|
||||
private static final int MSG_ON_UID_ACTIVE = 12;
|
||||
@@ -803,9 +815,9 @@ public class AppStateTrackerImpl implements AppStateTracker {
|
||||
obtainMessage(MSG_FORCE_APP_STANDBY_FEATURE_FLAG_CHANGED).sendToTarget();
|
||||
}
|
||||
|
||||
public void notifyExemptBucketChanged() {
|
||||
removeMessages(MSG_EXEMPT_BUCKET_CHANGED);
|
||||
obtainMessage(MSG_EXEMPT_BUCKET_CHANGED).sendToTarget();
|
||||
public void notifyExemptedBucketChanged() {
|
||||
removeMessages(MSG_EXEMPTED_BUCKET_CHANGED);
|
||||
obtainMessage(MSG_EXEMPTED_BUCKET_CHANGED).sendToTarget();
|
||||
}
|
||||
|
||||
public void doUserRemoved(int userId) {
|
||||
@@ -888,11 +900,11 @@ public class AppStateTrackerImpl implements AppStateTracker {
|
||||
mStatLogger.logDurationStat(Stats.TEMP_EXEMPTION_LIST_CHANGED, start);
|
||||
return;
|
||||
|
||||
case MSG_EXEMPT_BUCKET_CHANGED:
|
||||
case MSG_EXEMPTED_BUCKET_CHANGED:
|
||||
for (Listener l : cloneListeners()) {
|
||||
l.onExemptBucketChanged(sender);
|
||||
l.onExemptedBucketChanged(sender);
|
||||
}
|
||||
mStatLogger.logDurationStat(Stats.EXEMPT_BUCKET_CHANGED, start);
|
||||
mStatLogger.logDurationStat(Stats.EXEMPTED_BUCKET_CHANGED, start);
|
||||
return;
|
||||
|
||||
case MSG_FORCE_ALL_CHANGED:
|
||||
@@ -1005,7 +1017,7 @@ public class AppStateTrackerImpl implements AppStateTracker {
|
||||
}
|
||||
cleanUpArrayForUser(mActiveUids, removedUserId);
|
||||
cleanUpArrayForUser(mForegroundUids, removedUserId);
|
||||
mExemptBucketPackages.remove(removedUserId);
|
||||
mExemptedBucketPackages.remove(removedUserId);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1148,7 +1160,7 @@ public class AppStateTrackerImpl implements AppStateTracker {
|
||||
}
|
||||
final int userId = UserHandle.getUserId(uid);
|
||||
if (mAppStandbyInternal.isAppIdleEnabled() && !mAppStandbyInternal.isInParole()
|
||||
&& mExemptBucketPackages.contains(userId, packageName)) {
|
||||
&& mExemptedBucketPackages.contains(userId, packageName)) {
|
||||
return false;
|
||||
}
|
||||
return mForceAllAppsStandby;
|
||||
@@ -1301,14 +1313,14 @@ public class AppStateTrackerImpl implements AppStateTracker {
|
||||
|
||||
pw.println("Exempted bucket packages:");
|
||||
pw.increaseIndent();
|
||||
for (int i = 0; i < mExemptBucketPackages.size(); i++) {
|
||||
for (int i = 0; i < mExemptedBucketPackages.size(); i++) {
|
||||
pw.print("User ");
|
||||
pw.print(mExemptBucketPackages.keyAt(i));
|
||||
pw.print(mExemptedBucketPackages.keyAt(i));
|
||||
pw.println();
|
||||
|
||||
pw.increaseIndent();
|
||||
for (int j = 0; j < mExemptBucketPackages.sizeAt(i); j++) {
|
||||
pw.print(mExemptBucketPackages.valueAt(i, j));
|
||||
for (int j = 0; j < mExemptedBucketPackages.sizeAt(i); j++) {
|
||||
pw.print(mExemptedBucketPackages.valueAt(i, j));
|
||||
pw.println();
|
||||
}
|
||||
pw.decreaseIndent();
|
||||
@@ -1384,12 +1396,13 @@ public class AppStateTrackerImpl implements AppStateTracker {
|
||||
proto.write(AppStateTrackerProto.TEMP_POWER_SAVE_EXEMPT_APP_IDS, appId);
|
||||
}
|
||||
|
||||
for (int i = 0; i < mExemptBucketPackages.size(); i++) {
|
||||
for (int j = 0; j < mExemptBucketPackages.sizeAt(i); j++) {
|
||||
for (int i = 0; i < mExemptedBucketPackages.size(); i++) {
|
||||
for (int j = 0; j < mExemptedBucketPackages.sizeAt(i); j++) {
|
||||
final long token2 = proto.start(AppStateTrackerProto.EXEMPTED_BUCKET_PACKAGES);
|
||||
|
||||
proto.write(ExemptedPackage.USER_ID, mExemptBucketPackages.keyAt(i));
|
||||
proto.write(ExemptedPackage.PACKAGE_NAME, mExemptBucketPackages.valueAt(i, j));
|
||||
proto.write(ExemptedPackage.USER_ID, mExemptedBucketPackages.keyAt(i));
|
||||
proto.write(ExemptedPackage.PACKAGE_NAME,
|
||||
mExemptedBucketPackages.valueAt(i, j));
|
||||
|
||||
proto.end(token2);
|
||||
}
|
||||
|
||||
@@ -4310,7 +4310,7 @@ public class AlarmManagerService extends SystemService {
|
||||
filter.addAction(Intent.ACTION_PACKAGE_REMOVED);
|
||||
filter.addAction(Intent.ACTION_PACKAGE_RESTARTED);
|
||||
filter.addAction(Intent.ACTION_QUERY_PACKAGE_RESTART);
|
||||
filter.addDataScheme("package");
|
||||
filter.addDataScheme(IntentFilter.SCHEME_PACKAGE);
|
||||
getContext().registerReceiver(this, filter);
|
||||
// Register for events related to sdcard installation.
|
||||
IntentFilter sdFilter = new IntentFilter();
|
||||
|
||||
@@ -276,6 +276,14 @@ public class IntentFilter implements Parcelable {
|
||||
*/
|
||||
public static final String SCHEME_HTTPS = "https";
|
||||
|
||||
/**
|
||||
* Package scheme
|
||||
*
|
||||
* @see #addDataScheme(String)
|
||||
* @hide
|
||||
*/
|
||||
public static final String SCHEME_PACKAGE = "package";
|
||||
|
||||
/**
|
||||
* The value to indicate a wildcard for incoming match arguments.
|
||||
* @hide
|
||||
|
||||
@@ -48,6 +48,7 @@ import android.content.BroadcastReceiver;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.IntentFilter;
|
||||
import android.net.Uri;
|
||||
import android.os.BatteryManager;
|
||||
import android.os.Handler;
|
||||
import android.os.Looper;
|
||||
@@ -282,7 +283,7 @@ public class AppStateTrackerTest {
|
||||
eq(ServiceType.FORCE_ALL_APPS_STANDBY),
|
||||
powerSaveObserverCaptor.capture());
|
||||
|
||||
verify(mMockContext).registerReceiver(
|
||||
verify(mMockContext, times(2)).registerReceiver(
|
||||
receiverCaptor.capture(), any(IntentFilter.class));
|
||||
verify(mMockAppStandbyInternal).addListener(
|
||||
appIdleStateChangeListenerCaptor.capture());
|
||||
@@ -1242,6 +1243,67 @@ public class AppStateTrackerTest {
|
||||
assertTrue(instance.isForceAllAppsStandbyEnabled());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testStateClearedOnPackageRemoved() throws Exception {
|
||||
final AppStateTrackerTestable instance = newInstance();
|
||||
callStart(instance);
|
||||
|
||||
instance.mActiveUids.put(UID_1, true);
|
||||
instance.mForegroundUids.put(UID_2, true);
|
||||
instance.mRunAnyRestrictedPackages.add(Pair.create(UID_1, PACKAGE_1));
|
||||
instance.mExemptedBucketPackages.add(UserHandle.getUserId(UID_2), PACKAGE_2);
|
||||
|
||||
// Replace PACKAGE_1, nothing should change
|
||||
Intent packageRemoved = new Intent(Intent.ACTION_PACKAGE_REMOVED)
|
||||
.putExtra(Intent.EXTRA_USER_HANDLE, UserHandle.getUserId(UID_1))
|
||||
.putExtra(Intent.EXTRA_UID, UID_1)
|
||||
.putExtra(Intent.EXTRA_REPLACING, true)
|
||||
.setData(Uri.fromParts(IntentFilter.SCHEME_PACKAGE, PACKAGE_1, null));
|
||||
mReceiver.onReceive(mMockContext, packageRemoved);
|
||||
|
||||
assertEquals(1, instance.mActiveUids.size());
|
||||
assertEquals(1, instance.mForegroundUids.size());
|
||||
assertEquals(1, instance.mRunAnyRestrictedPackages.size());
|
||||
assertEquals(1, instance.mExemptedBucketPackages.size());
|
||||
|
||||
// Replace PACKAGE_2, nothing should change
|
||||
packageRemoved = new Intent(Intent.ACTION_PACKAGE_REMOVED)
|
||||
.putExtra(Intent.EXTRA_USER_HANDLE, UserHandle.getUserId(UID_2))
|
||||
.putExtra(Intent.EXTRA_UID, UID_2)
|
||||
.putExtra(Intent.EXTRA_REPLACING, true)
|
||||
.setData(Uri.fromParts(IntentFilter.SCHEME_PACKAGE, PACKAGE_2, null));
|
||||
mReceiver.onReceive(mMockContext, packageRemoved);
|
||||
|
||||
assertEquals(1, instance.mActiveUids.size());
|
||||
assertEquals(1, instance.mForegroundUids.size());
|
||||
assertEquals(1, instance.mRunAnyRestrictedPackages.size());
|
||||
assertEquals(1, instance.mExemptedBucketPackages.size());
|
||||
|
||||
// Remove PACKAGE_1
|
||||
packageRemoved = new Intent(Intent.ACTION_PACKAGE_REMOVED)
|
||||
.putExtra(Intent.EXTRA_USER_HANDLE, UserHandle.getUserId(UID_1))
|
||||
.putExtra(Intent.EXTRA_UID, UID_1)
|
||||
.setData(Uri.fromParts(IntentFilter.SCHEME_PACKAGE, PACKAGE_1, null));
|
||||
mReceiver.onReceive(mMockContext, packageRemoved);
|
||||
|
||||
assertEquals(0, instance.mActiveUids.size());
|
||||
assertEquals(1, instance.mForegroundUids.size());
|
||||
assertEquals(0, instance.mRunAnyRestrictedPackages.size());
|
||||
assertEquals(1, instance.mExemptedBucketPackages.size());
|
||||
|
||||
// Remove PACKAGE_2
|
||||
packageRemoved = new Intent(Intent.ACTION_PACKAGE_REMOVED)
|
||||
.putExtra(Intent.EXTRA_USER_HANDLE, UserHandle.getUserId(UID_2))
|
||||
.putExtra(Intent.EXTRA_UID, UID_2)
|
||||
.setData(Uri.fromParts(IntentFilter.SCHEME_PACKAGE, PACKAGE_2, null));
|
||||
mReceiver.onReceive(mMockContext, packageRemoved);
|
||||
|
||||
assertEquals(0, instance.mActiveUids.size());
|
||||
assertEquals(0, instance.mForegroundUids.size());
|
||||
assertEquals(0, instance.mRunAnyRestrictedPackages.size());
|
||||
assertEquals(0, instance.mExemptedBucketPackages.size());
|
||||
}
|
||||
|
||||
static int[] array(int... appIds) {
|
||||
Arrays.sort(appIds);
|
||||
return appIds;
|
||||
|
||||
Reference in New Issue
Block a user