Loading core/java/android/content/Intent.java +12 −0 Original line number Diff line number Diff line Loading @@ -2444,6 +2444,18 @@ public class Intent implements Parcelable, Cloneable { @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) public static final String ACTION_PACKAGE_ENABLE_ROLLBACK = "android.intent.action.PACKAGE_ENABLE_ROLLBACK"; /** * Broadcast Action: Sent to the system rollback manager when the rollback for a certain * package needs to be cancelled. * * <p class="note">This intent is sent by PackageManagerService to notify RollbackManager * that enabling a specific rollback has timed out. * * @hide */ @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) public static final String ACTION_CANCEL_ENABLE_ROLLBACK = "android.intent.action.CANCEL_ENABLE_ROLLBACK"; /** * Broadcast Action: A rollback has been committed. * Loading core/java/android/content/rollback/RollbackManager.java +2 −2 Original line number Diff line number Diff line Loading @@ -40,7 +40,7 @@ import java.util.List; * used to initiate rollback of those packages for a limited time period after * upgrade. * * @see PackageInstaller.SessionParams#setEnableRollback() * @see PackageInstaller.SessionParams#setEnableRollback(boolean) * @hide */ @SystemApi @TestApi Loading @@ -52,7 +52,7 @@ public final class RollbackManager { /** * Lifetime duration of rollback packages in millis. A rollback will be available for * at most that duration of time after a package is installed with * {@link PackageInstaller.SessionParams#setEnableRollback()}. * {@link PackageInstaller.SessionParams#setEnableRollback(boolean)}. * * <p>If flag value is negative, the default value will be assigned. * Loading core/res/AndroidManifest.xml +1 −0 Original line number Diff line number Diff line Loading @@ -43,6 +43,7 @@ <protected-broadcast android:name="android.intent.action.PACKAGE_FULLY_REMOVED" /> <protected-broadcast android:name="android.intent.action.PACKAGE_CHANGED" /> <protected-broadcast android:name="android.intent.action.PACKAGE_ENABLE_ROLLBACK" /> <protected-broadcast android:name="android.intent.action.CANCEL_ENABLE_ROLLBACK" /> <protected-broadcast android:name="android.intent.action.ROLLBACK_COMMITTED" /> <protected-broadcast android:name="android.intent.action.PACKAGE_RESTARTED" /> <protected-broadcast android:name="android.intent.action.PACKAGE_DATA_CLEARED" /> Loading services/core/java/com/android/server/pm/PackageManagerService.java +9 −0 Original line number Diff line number Diff line Loading @@ -1746,6 +1746,15 @@ public class PackageManagerService extends IPackageManager.Stub Trace.asyncTraceEnd( TRACE_TAG_PACKAGE_MANAGER, "enable_rollback", enableRollbackToken); params.handleRollbackEnabled(); Intent rollbackTimeoutIntent = new Intent( Intent.ACTION_CANCEL_ENABLE_ROLLBACK); rollbackTimeoutIntent.putExtra( PackageManagerInternal.EXTRA_ENABLE_ROLLBACK_TOKEN, enableRollbackToken); rollbackTimeoutIntent.addFlags( Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT); mContext.sendBroadcastAsUser(rollbackTimeoutIntent, UserHandle.SYSTEM, android.Manifest.permission.PACKAGE_ROLLBACK_AGENT); } break; } services/core/java/com/android/server/rollback/RollbackManagerServiceImpl.java +59 −3 Original line number Diff line number Diff line Loading @@ -184,7 +184,7 @@ class RollbackManagerServiceImpl extends IRollbackManager.Stub { getHandler().post(() -> { boolean success = enableRollback(installFlags, newPackageCodePath, installedUsers, user); installedUsers, user, token); int ret = PackageManagerInternal.ENABLE_ROLLBACK_SUCCEEDED; if (!success) { ret = PackageManagerInternal.ENABLE_ROLLBACK_FAILED; Loading @@ -203,6 +203,27 @@ class RollbackManagerServiceImpl extends IRollbackManager.Stub { } }, enableRollbackFilter, null, getHandler()); IntentFilter enableRollbackTimedOutFilter = new IntentFilter(); enableRollbackTimedOutFilter.addAction(Intent.ACTION_CANCEL_ENABLE_ROLLBACK); mContext.registerReceiver(new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { if (Intent.ACTION_CANCEL_ENABLE_ROLLBACK.equals(intent.getAction())) { int token = intent.getIntExtra( PackageManagerInternal.EXTRA_ENABLE_ROLLBACK_TOKEN, -1); synchronized (mLock) { for (NewRollback rollback : mNewRollbacks) { if (rollback.hasToken(token)) { rollback.isCancelled = true; return; } } } } } }, enableRollbackTimedOutFilter, null, getHandler()); registerTimeChangeReceiver(); } Loading Loading @@ -818,10 +839,11 @@ class RollbackManagerServiceImpl extends IRollbackManager.Stub { * @param newPackageCodePath path to the package about to be installed. * @param installedUsers the set of users for which a given package is installed. * @param user the user that owns the install session to enable rollback on. * @param token the distinct rollback token sent by package manager. * @return true if enabling the rollback succeeds, false otherwise. */ private boolean enableRollback(int installFlags, File newPackageCodePath, int[] installedUsers, @UserIdInt int user) { int[] installedUsers, @UserIdInt int user, int token) { // Find the session id associated with this install. // TODO: It would be nice if package manager or package installer told Loading Loading @@ -914,6 +936,7 @@ class RollbackManagerServiceImpl extends IRollbackManager.Stub { mNewRollbacks.add(newRollback); } } newRollback.addToken(token); return enableRollbackForPackageSession(newRollback.data, packageSession, installedUsers, /* snapshotUserData*/ true); Loading Loading @@ -1016,7 +1039,7 @@ class RollbackManagerServiceImpl extends IRollbackManager.Stub { public void restoreUserData(String packageName, int[] userIds, int appId, long ceDataInode, String seInfo, int token) { if (Binder.getCallingUid() != Process.SYSTEM_UID) { throw new SecurityException("restoureUserData may only be called by the system."); throw new SecurityException("restoreUserData may only be called by the system."); } getHandler().post(() -> { Loading Loading @@ -1272,6 +1295,11 @@ class RollbackManagerServiceImpl extends IRollbackManager.Stub { deleteRollback(data); return null; } if (newRollback.isCancelled) { Log.e(TAG, "Rollback has been cancelled by PackageManager"); deleteRollback(data); return null; } // It's safe to access data.info outside a synchronized block because // this is running on the handler thread and all changes to the Loading Loading @@ -1451,6 +1479,13 @@ class RollbackManagerServiceImpl extends IRollbackManager.Stub { private static class NewRollback { public final RollbackData data; /** * This array holds all of the rollback tokens associated with package sessions included * in this rollback. This is used to identify which rollback should be cancelled in case * {@link PackageManager} sends an {@link Intent#ACTION_CANCEL_ENABLE_ROLLBACK} intent. */ private final IntArray mTokens = new IntArray(); /** * Session ids for all packages in the install. * For multi-package sessions, this is the list of child session ids. Loading @@ -1459,10 +1494,31 @@ class RollbackManagerServiceImpl extends IRollbackManager.Stub { */ public final int[] packageSessionIds; /** * Flag to determine whether the RollbackData has been cancelled. * * <p>RollbackData could be invalidated and cancelled if RollbackManager receives * {@link Intent#ACTION_CANCEL_ENABLE_ROLLBACK} from {@link PackageManager}. * * <p>The main underlying assumption here is that if enabling the rollback times out, then * {@link PackageManager} will NOT send * {@link PackageInstaller.SessionCallback#onFinished(int, boolean)} before it broadcasts * {@link Intent#ACTION_CANCEL_ENABLE_ROLLBACK}. */ public boolean isCancelled = false; NewRollback(RollbackData data, int[] packageSessionIds) { this.data = data; this.packageSessionIds = packageSessionIds; } public void addToken(int token) { mTokens.add(token); } public boolean hasToken(int token) { return mTokens.indexOf(token) != -1; } } NewRollback createNewRollbackLocked(PackageInstaller.SessionInfo parentSession) { Loading Loading
core/java/android/content/Intent.java +12 −0 Original line number Diff line number Diff line Loading @@ -2444,6 +2444,18 @@ public class Intent implements Parcelable, Cloneable { @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) public static final String ACTION_PACKAGE_ENABLE_ROLLBACK = "android.intent.action.PACKAGE_ENABLE_ROLLBACK"; /** * Broadcast Action: Sent to the system rollback manager when the rollback for a certain * package needs to be cancelled. * * <p class="note">This intent is sent by PackageManagerService to notify RollbackManager * that enabling a specific rollback has timed out. * * @hide */ @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) public static final String ACTION_CANCEL_ENABLE_ROLLBACK = "android.intent.action.CANCEL_ENABLE_ROLLBACK"; /** * Broadcast Action: A rollback has been committed. * Loading
core/java/android/content/rollback/RollbackManager.java +2 −2 Original line number Diff line number Diff line Loading @@ -40,7 +40,7 @@ import java.util.List; * used to initiate rollback of those packages for a limited time period after * upgrade. * * @see PackageInstaller.SessionParams#setEnableRollback() * @see PackageInstaller.SessionParams#setEnableRollback(boolean) * @hide */ @SystemApi @TestApi Loading @@ -52,7 +52,7 @@ public final class RollbackManager { /** * Lifetime duration of rollback packages in millis. A rollback will be available for * at most that duration of time after a package is installed with * {@link PackageInstaller.SessionParams#setEnableRollback()}. * {@link PackageInstaller.SessionParams#setEnableRollback(boolean)}. * * <p>If flag value is negative, the default value will be assigned. * Loading
core/res/AndroidManifest.xml +1 −0 Original line number Diff line number Diff line Loading @@ -43,6 +43,7 @@ <protected-broadcast android:name="android.intent.action.PACKAGE_FULLY_REMOVED" /> <protected-broadcast android:name="android.intent.action.PACKAGE_CHANGED" /> <protected-broadcast android:name="android.intent.action.PACKAGE_ENABLE_ROLLBACK" /> <protected-broadcast android:name="android.intent.action.CANCEL_ENABLE_ROLLBACK" /> <protected-broadcast android:name="android.intent.action.ROLLBACK_COMMITTED" /> <protected-broadcast android:name="android.intent.action.PACKAGE_RESTARTED" /> <protected-broadcast android:name="android.intent.action.PACKAGE_DATA_CLEARED" /> Loading
services/core/java/com/android/server/pm/PackageManagerService.java +9 −0 Original line number Diff line number Diff line Loading @@ -1746,6 +1746,15 @@ public class PackageManagerService extends IPackageManager.Stub Trace.asyncTraceEnd( TRACE_TAG_PACKAGE_MANAGER, "enable_rollback", enableRollbackToken); params.handleRollbackEnabled(); Intent rollbackTimeoutIntent = new Intent( Intent.ACTION_CANCEL_ENABLE_ROLLBACK); rollbackTimeoutIntent.putExtra( PackageManagerInternal.EXTRA_ENABLE_ROLLBACK_TOKEN, enableRollbackToken); rollbackTimeoutIntent.addFlags( Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT); mContext.sendBroadcastAsUser(rollbackTimeoutIntent, UserHandle.SYSTEM, android.Manifest.permission.PACKAGE_ROLLBACK_AGENT); } break; }
services/core/java/com/android/server/rollback/RollbackManagerServiceImpl.java +59 −3 Original line number Diff line number Diff line Loading @@ -184,7 +184,7 @@ class RollbackManagerServiceImpl extends IRollbackManager.Stub { getHandler().post(() -> { boolean success = enableRollback(installFlags, newPackageCodePath, installedUsers, user); installedUsers, user, token); int ret = PackageManagerInternal.ENABLE_ROLLBACK_SUCCEEDED; if (!success) { ret = PackageManagerInternal.ENABLE_ROLLBACK_FAILED; Loading @@ -203,6 +203,27 @@ class RollbackManagerServiceImpl extends IRollbackManager.Stub { } }, enableRollbackFilter, null, getHandler()); IntentFilter enableRollbackTimedOutFilter = new IntentFilter(); enableRollbackTimedOutFilter.addAction(Intent.ACTION_CANCEL_ENABLE_ROLLBACK); mContext.registerReceiver(new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { if (Intent.ACTION_CANCEL_ENABLE_ROLLBACK.equals(intent.getAction())) { int token = intent.getIntExtra( PackageManagerInternal.EXTRA_ENABLE_ROLLBACK_TOKEN, -1); synchronized (mLock) { for (NewRollback rollback : mNewRollbacks) { if (rollback.hasToken(token)) { rollback.isCancelled = true; return; } } } } } }, enableRollbackTimedOutFilter, null, getHandler()); registerTimeChangeReceiver(); } Loading Loading @@ -818,10 +839,11 @@ class RollbackManagerServiceImpl extends IRollbackManager.Stub { * @param newPackageCodePath path to the package about to be installed. * @param installedUsers the set of users for which a given package is installed. * @param user the user that owns the install session to enable rollback on. * @param token the distinct rollback token sent by package manager. * @return true if enabling the rollback succeeds, false otherwise. */ private boolean enableRollback(int installFlags, File newPackageCodePath, int[] installedUsers, @UserIdInt int user) { int[] installedUsers, @UserIdInt int user, int token) { // Find the session id associated with this install. // TODO: It would be nice if package manager or package installer told Loading Loading @@ -914,6 +936,7 @@ class RollbackManagerServiceImpl extends IRollbackManager.Stub { mNewRollbacks.add(newRollback); } } newRollback.addToken(token); return enableRollbackForPackageSession(newRollback.data, packageSession, installedUsers, /* snapshotUserData*/ true); Loading Loading @@ -1016,7 +1039,7 @@ class RollbackManagerServiceImpl extends IRollbackManager.Stub { public void restoreUserData(String packageName, int[] userIds, int appId, long ceDataInode, String seInfo, int token) { if (Binder.getCallingUid() != Process.SYSTEM_UID) { throw new SecurityException("restoureUserData may only be called by the system."); throw new SecurityException("restoreUserData may only be called by the system."); } getHandler().post(() -> { Loading Loading @@ -1272,6 +1295,11 @@ class RollbackManagerServiceImpl extends IRollbackManager.Stub { deleteRollback(data); return null; } if (newRollback.isCancelled) { Log.e(TAG, "Rollback has been cancelled by PackageManager"); deleteRollback(data); return null; } // It's safe to access data.info outside a synchronized block because // this is running on the handler thread and all changes to the Loading Loading @@ -1451,6 +1479,13 @@ class RollbackManagerServiceImpl extends IRollbackManager.Stub { private static class NewRollback { public final RollbackData data; /** * This array holds all of the rollback tokens associated with package sessions included * in this rollback. This is used to identify which rollback should be cancelled in case * {@link PackageManager} sends an {@link Intent#ACTION_CANCEL_ENABLE_ROLLBACK} intent. */ private final IntArray mTokens = new IntArray(); /** * Session ids for all packages in the install. * For multi-package sessions, this is the list of child session ids. Loading @@ -1459,10 +1494,31 @@ class RollbackManagerServiceImpl extends IRollbackManager.Stub { */ public final int[] packageSessionIds; /** * Flag to determine whether the RollbackData has been cancelled. * * <p>RollbackData could be invalidated and cancelled if RollbackManager receives * {@link Intent#ACTION_CANCEL_ENABLE_ROLLBACK} from {@link PackageManager}. * * <p>The main underlying assumption here is that if enabling the rollback times out, then * {@link PackageManager} will NOT send * {@link PackageInstaller.SessionCallback#onFinished(int, boolean)} before it broadcasts * {@link Intent#ACTION_CANCEL_ENABLE_ROLLBACK}. */ public boolean isCancelled = false; NewRollback(RollbackData data, int[] packageSessionIds) { this.data = data; this.packageSessionIds = packageSessionIds; } public void addToken(int token) { mTokens.add(token); } public boolean hasToken(int token) { return mTokens.indexOf(token) != -1; } } NewRollback createNewRollbackLocked(PackageInstaller.SessionInfo parentSession) { Loading