Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit f66eab85 authored by Bryan's avatar Bryan Committed by Bryan Mawhinney
Browse files

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
parent b886e41a
Loading
Loading
Loading
Loading
+4 −4
Original line number Diff line number Diff line
@@ -47,9 +47,9 @@ public class AppWidgetBackupBridge {
                : null;
    }

    public static void restoreStarting(int userId) {
    public static void systemRestoreStarting(int userId) {
        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) {
            sAppWidgetService.restoreFinished(userId);
            sAppWidgetService.systemRestoreFinished(userId);
        }
    }
}
+2 −2
Original line number Diff line number Diff line
@@ -28,7 +28,7 @@ import java.util.List;
public interface WidgetBackupProvider {
    public List<String> getWidgetParticipants(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 restoreFinished(int userId);
    public void systemRestoreFinished(int userId);
}
+90 −55
Original line number Diff line number Diff line
@@ -409,6 +409,8 @@ class AppWidgetServiceImpl extends IAppWidgetService.Stub implements WidgetBacku

                // If the set of providers has been modified, notify each active AppWidgetHost
                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
    public void restoreStarting(int userId) {
        mBackupRestoreController.restoreStarting(userId);
    public void systemRestoreStarting(int userId) {
        mBackupRestoreController.systemRestoreStarting(userId);
    }

    @Override
@@ -2481,8 +2483,8 @@ class AppWidgetServiceImpl extends IAppWidgetService.Stub implements WidgetBacku
    }

    @Override
    public void restoreFinished(int userId) {
        mBackupRestoreController.restoreFinished(userId);
    public void systemRestoreFinished(int userId) {
        mBackupRestoreController.systemRestoreFinished(userId);
    }

    @SuppressWarnings("deprecation")
@@ -4272,6 +4274,9 @@ class AppWidgetServiceImpl extends IAppWidgetService.Stub implements WidgetBacku
        private final HashMap<Host, ArrayList<RestoreUpdateRecord>> mUpdatesByHost =
                new HashMap<>();

        @GuardedBy("mLock")
        private boolean mHasSystemRestoreFinished;

        public List<String> getWidgetParticipants(int userId) {
            if (DEBUG) {
                Slog.i(TAG, "Getting widget participants for user: " + userId);
@@ -4375,12 +4380,13 @@ class AppWidgetServiceImpl extends IAppWidgetService.Stub implements WidgetBacku
            return stream.toByteArray();
        }

        public void restoreStarting(int userId) {
        public void systemRestoreStarting(int userId) {
            if (DEBUG) {
                Slog.i(TAG, "Restore starting for user: " + userId);
                Slog.i(TAG, "System restore starting for user: " + userId);
            }

            synchronized (mLock) {
                mHasSystemRestoreFinished = false;
                // 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
                // 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
        // the new widget ID space.
        public void restoreFinished(int userId) {
        // the new widget ID space.  Apps that are not yet installed will be notifed when they are.
        public void systemRestoreFinished(int userId) {
            if (DEBUG) {
                Slog.i(TAG, "restoreFinished for " + userId);
                Slog.i(TAG, "systemRestoreFinished for " + userId);
            }
            synchronized (mLock) {
                mHasSystemRestoreFinished = true;
                maybeSendWidgetRestoreBroadcastsLocked(userId);
            }
        }

            final UserHandle userHandle = new UserHandle(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);
            // Build the providers' broadcasts and send them off
            Set<Map.Entry<Provider, ArrayList<RestoreUpdateRecord>>> providerEntries
                    = mUpdatesByProvider.entrySet();
            for (Map.Entry<Provider, ArrayList<RestoreUpdateRecord>> e : providerEntries) {
                // For each provider there's a list of affected IDs
                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();
                final int pending = countPendingUpdates(updates);
                if (DEBUG) {
@@ -4621,7 +4657,6 @@ class AppWidgetServiceImpl extends IAppWidgetService.Stub implements WidgetBacku
                }
            }
        }
        }

        private Provider findProviderLocked(ComponentName componentName, int userId) {
            final int providerCount = mProviders.size();
+5 −3
Original line number Diff line number Diff line
@@ -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 (mIsSystemRestore) {
            AppWidgetBackupBridge.restoreStarting(mUserId);
            AppWidgetBackupBridge.systemRestoreStarting(mUserId);
        }

        try {
@@ -1133,8 +1133,10 @@ public class PerformUnifiedRestoreTask implements BackupRestoreTask {
                    restoreAgentTimeoutMillis);
        }

        if (mIsSystemRestore) {
            // 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
        // dataset information