Changes to how we notify widget restore participants of new ids
As part of widget restore, we need to notify participants (hosts & providers) of the mapping between ancestral and new widget ids. Prior to this change, this was done at the end of system restore and after each restore-at-install of unbundled apps. There were two issues with this: 1) We would try to notify not-yet-installed participants at the end of system restore and then *not* try again when they were installed. 2) We relied on PACKAGE_ADDED broadcasts to know which participants were installed, but these are delivered asynchronously and not guaranteed to be processed before the restoreFinished call. After this change, we: 1) Only notify participants that are actually installed 2) Use receipt of the PACKAGE_ADDED / CHANGED broadcast to trigger notification of any restore participants that are added or changed *after* system restore completes. 2 is safe because by the time PackageManager sends the package added / changed broadcasts, the app data restore has been completed, and the app has been killed if needed. Bug: 162057170 Test: Manual restore of Keep widget via cloud and d2d Change-Id: I51dec33d09b62faba6d7c7daacd718a3c0682f7d
This commit is contained in:
@@ -47,9 +47,9 @@ public class AppWidgetBackupBridge {
|
|||||||
: null;
|
: null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void restoreStarting(int userId) {
|
public static void systemRestoreStarting(int userId) {
|
||||||
if (sAppWidgetService != null) {
|
if (sAppWidgetService != null) {
|
||||||
sAppWidgetService.restoreStarting(userId);
|
sAppWidgetService.systemRestoreStarting(userId);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -59,9 +59,9 @@ public class AppWidgetBackupBridge {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void restoreFinished(int userId) {
|
public static void systemRestoreFinished(int userId) {
|
||||||
if (sAppWidgetService != null) {
|
if (sAppWidgetService != null) {
|
||||||
sAppWidgetService.restoreFinished(userId);
|
sAppWidgetService.systemRestoreFinished(userId);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -28,7 +28,7 @@ import java.util.List;
|
|||||||
public interface WidgetBackupProvider {
|
public interface WidgetBackupProvider {
|
||||||
public List<String> getWidgetParticipants(int userId);
|
public List<String> getWidgetParticipants(int userId);
|
||||||
public byte[] getWidgetState(String packageName, int userId);
|
public byte[] getWidgetState(String packageName, int userId);
|
||||||
public void restoreStarting(int userId);
|
public void systemRestoreStarting(int userId);
|
||||||
public void restoreWidgetState(String packageName, byte[] restoredState, int userId);
|
public void restoreWidgetState(String packageName, byte[] restoredState, int userId);
|
||||||
public void restoreFinished(int userId);
|
public void systemRestoreFinished(int userId);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -409,6 +409,8 @@ class AppWidgetServiceImpl extends IAppWidgetService.Stub implements WidgetBacku
|
|||||||
|
|
||||||
// If the set of providers has been modified, notify each active AppWidgetHost
|
// If the set of providers has been modified, notify each active AppWidgetHost
|
||||||
scheduleNotifyGroupHostsForProvidersChangedLocked(userId);
|
scheduleNotifyGroupHostsForProvidersChangedLocked(userId);
|
||||||
|
// Possibly notify any new components of widget id changes
|
||||||
|
mBackupRestoreController.widgetComponentsChanged(userId);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -2471,8 +2473,8 @@ class AppWidgetServiceImpl extends IAppWidgetService.Stub implements WidgetBacku
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void restoreStarting(int userId) {
|
public void systemRestoreStarting(int userId) {
|
||||||
mBackupRestoreController.restoreStarting(userId);
|
mBackupRestoreController.systemRestoreStarting(userId);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -2481,8 +2483,8 @@ class AppWidgetServiceImpl extends IAppWidgetService.Stub implements WidgetBacku
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void restoreFinished(int userId) {
|
public void systemRestoreFinished(int userId) {
|
||||||
mBackupRestoreController.restoreFinished(userId);
|
mBackupRestoreController.systemRestoreFinished(userId);
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressWarnings("deprecation")
|
@SuppressWarnings("deprecation")
|
||||||
@@ -4272,6 +4274,9 @@ class AppWidgetServiceImpl extends IAppWidgetService.Stub implements WidgetBacku
|
|||||||
private final HashMap<Host, ArrayList<RestoreUpdateRecord>> mUpdatesByHost =
|
private final HashMap<Host, ArrayList<RestoreUpdateRecord>> mUpdatesByHost =
|
||||||
new HashMap<>();
|
new HashMap<>();
|
||||||
|
|
||||||
|
@GuardedBy("mLock")
|
||||||
|
private boolean mHasSystemRestoreFinished;
|
||||||
|
|
||||||
public List<String> getWidgetParticipants(int userId) {
|
public List<String> getWidgetParticipants(int userId) {
|
||||||
if (DEBUG) {
|
if (DEBUG) {
|
||||||
Slog.i(TAG, "Getting widget participants for user: " + userId);
|
Slog.i(TAG, "Getting widget participants for user: " + userId);
|
||||||
@@ -4375,12 +4380,13 @@ class AppWidgetServiceImpl extends IAppWidgetService.Stub implements WidgetBacku
|
|||||||
return stream.toByteArray();
|
return stream.toByteArray();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void restoreStarting(int userId) {
|
public void systemRestoreStarting(int userId) {
|
||||||
if (DEBUG) {
|
if (DEBUG) {
|
||||||
Slog.i(TAG, "Restore starting for user: " + userId);
|
Slog.i(TAG, "System restore starting for user: " + userId);
|
||||||
}
|
}
|
||||||
|
|
||||||
synchronized (mLock) {
|
synchronized (mLock) {
|
||||||
|
mHasSystemRestoreFinished = false;
|
||||||
// We're starting a new "system" restore operation, so any widget restore
|
// We're starting a new "system" restore operation, so any widget restore
|
||||||
// state that we see from here on is intended to replace the current
|
// state that we see from here on is intended to replace the current
|
||||||
// widget configuration of any/all of the affected apps.
|
// widget configuration of any/all of the affected apps.
|
||||||
@@ -4542,22 +4548,52 @@ class AppWidgetServiceImpl extends IAppWidgetService.Stub implements WidgetBacku
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Called once following the conclusion of a restore operation. This is when we
|
// Called once following the conclusion of a system restore operation. This is when we
|
||||||
// send out updates to apps involved in widget-state restore telling them about
|
// send out updates to apps involved in widget-state restore telling them about
|
||||||
// the new widget ID space.
|
// the new widget ID space. Apps that are not yet installed will be notifed when they are.
|
||||||
public void restoreFinished(int userId) {
|
public void systemRestoreFinished(int userId) {
|
||||||
if (DEBUG) {
|
if (DEBUG) {
|
||||||
Slog.i(TAG, "restoreFinished for " + userId);
|
Slog.i(TAG, "systemRestoreFinished for " + userId);
|
||||||
|
}
|
||||||
|
synchronized (mLock) {
|
||||||
|
mHasSystemRestoreFinished = true;
|
||||||
|
maybeSendWidgetRestoreBroadcastsLocked(userId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Called when widget components (hosts or providers) are added or changed. If system
|
||||||
|
// restore has completed, we use this opportunity to tell the apps to update to the new
|
||||||
|
// widget ID space. If system restore is still in progress, we delay the updates until
|
||||||
|
// the end, to allow all participants to restore their state before updating widget IDs.
|
||||||
|
public void widgetComponentsChanged(int userId) {
|
||||||
|
synchronized (mLock) {
|
||||||
|
if (mHasSystemRestoreFinished) {
|
||||||
|
maybeSendWidgetRestoreBroadcastsLocked(userId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Called following the conclusion of a restore operation and when widget components
|
||||||
|
// are added or changed. This is when we send out updates to apps involved in widget-state
|
||||||
|
// restore telling them about the new widget ID space.
|
||||||
|
@GuardedBy("mLock")
|
||||||
|
private void maybeSendWidgetRestoreBroadcastsLocked(int userId) {
|
||||||
|
if (DEBUG) {
|
||||||
|
Slog.i(TAG, "maybeSendWidgetRestoreBroadcasts for " + userId);
|
||||||
}
|
}
|
||||||
|
|
||||||
final UserHandle userHandle = new UserHandle(userId);
|
final UserHandle userHandle = new UserHandle(userId);
|
||||||
synchronized (mLock) {
|
|
||||||
// Build the providers' broadcasts and send them off
|
// Build the providers' broadcasts and send them off
|
||||||
Set<Map.Entry<Provider, ArrayList<RestoreUpdateRecord>>> providerEntries
|
Set<Map.Entry<Provider, ArrayList<RestoreUpdateRecord>>> providerEntries
|
||||||
= mUpdatesByProvider.entrySet();
|
= mUpdatesByProvider.entrySet();
|
||||||
for (Map.Entry<Provider, ArrayList<RestoreUpdateRecord>> e : providerEntries) {
|
for (Map.Entry<Provider, ArrayList<RestoreUpdateRecord>> e : providerEntries) {
|
||||||
// For each provider there's a list of affected IDs
|
// For each provider there's a list of affected IDs
|
||||||
Provider provider = e.getKey();
|
Provider provider = e.getKey();
|
||||||
|
if (provider.zombie) {
|
||||||
|
// Provider not installed, we can't send them broadcasts yet.
|
||||||
|
// We'll be called again when the provider is installed.
|
||||||
|
continue;
|
||||||
|
}
|
||||||
ArrayList<RestoreUpdateRecord> updates = e.getValue();
|
ArrayList<RestoreUpdateRecord> updates = e.getValue();
|
||||||
final int pending = countPendingUpdates(updates);
|
final int pending = countPendingUpdates(updates);
|
||||||
if (DEBUG) {
|
if (DEBUG) {
|
||||||
@@ -4621,7 +4657,6 @@ class AppWidgetServiceImpl extends IAppWidgetService.Stub implements WidgetBacku
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
private Provider findProviderLocked(ComponentName componentName, int userId) {
|
private Provider findProviderLocked(ComponentName componentName, int userId) {
|
||||||
final int providerCount = mProviders.size();
|
final int providerCount = mProviders.size();
|
||||||
|
|||||||
@@ -381,7 +381,7 @@ public class PerformUnifiedRestoreTask implements BackupRestoreTask {
|
|||||||
|
|
||||||
// If we're starting a full-system restore, set up to begin widget ID remapping
|
// If we're starting a full-system restore, set up to begin widget ID remapping
|
||||||
if (mIsSystemRestore) {
|
if (mIsSystemRestore) {
|
||||||
AppWidgetBackupBridge.restoreStarting(mUserId);
|
AppWidgetBackupBridge.systemRestoreStarting(mUserId);
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
@@ -1133,8 +1133,10 @@ public class PerformUnifiedRestoreTask implements BackupRestoreTask {
|
|||||||
restoreAgentTimeoutMillis);
|
restoreAgentTimeoutMillis);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (mIsSystemRestore) {
|
||||||
// Kick off any work that may be needed regarding app widget restores
|
// Kick off any work that may be needed regarding app widget restores
|
||||||
AppWidgetBackupBridge.restoreFinished(mUserId);
|
AppWidgetBackupBridge.systemRestoreFinished(mUserId);
|
||||||
|
}
|
||||||
|
|
||||||
// If this was a full-system restore, record the ancestral
|
// If this was a full-system restore, record the ancestral
|
||||||
// dataset information
|
// dataset information
|
||||||
|
|||||||
Reference in New Issue
Block a user