mirror of
https://github.com/LawnchairLauncher/lawnchair.git
synced 2026-02-28 07:46:55 +00:00
After SuW the favorite table is copied into backup table, but the widget id in the backup table hasn't been migrated. This introduces general unstabality and can sometimes leads to the disappearance of widgets after a restore. Bug: 171774227 Test: run Backup Restore flows and verified database status with arbitrary logging Change-Id: If275a6b5395504d6de90e26c3998f759e797f6e1
122 lines
5.4 KiB
Java
122 lines
5.4 KiB
Java
package com.android.launcher3;
|
|
|
|
import static android.os.Process.myUserHandle;
|
|
|
|
import android.appwidget.AppWidgetHost;
|
|
import android.appwidget.AppWidgetManager;
|
|
import android.appwidget.AppWidgetProviderInfo;
|
|
import android.content.BroadcastReceiver;
|
|
import android.content.ContentResolver;
|
|
import android.content.Context;
|
|
import android.content.Intent;
|
|
import android.database.Cursor;
|
|
import android.util.Log;
|
|
|
|
import androidx.annotation.WorkerThread;
|
|
|
|
import com.android.launcher3.LauncherSettings.Favorites;
|
|
import com.android.launcher3.model.LoaderTask;
|
|
import com.android.launcher3.model.WidgetsModel;
|
|
import com.android.launcher3.model.data.LauncherAppWidgetInfo;
|
|
import com.android.launcher3.pm.UserCache;
|
|
import com.android.launcher3.provider.RestoreDbTask;
|
|
import com.android.launcher3.util.ContentWriter;
|
|
|
|
public class AppWidgetsRestoredReceiver extends BroadcastReceiver {
|
|
|
|
private static final String TAG = "AWRestoredReceiver";
|
|
|
|
@Override
|
|
public void onReceive(final Context context, Intent intent) {
|
|
if (AppWidgetManager.ACTION_APPWIDGET_HOST_RESTORED.equals(intent.getAction())) {
|
|
int hostId = intent.getIntExtra(AppWidgetManager.EXTRA_HOST_ID, 0);
|
|
Log.d(TAG, "Widget ID map received for host:" + hostId);
|
|
if (hostId != LauncherAppWidgetHost.APPWIDGET_HOST_ID) {
|
|
return;
|
|
}
|
|
|
|
final int[] oldIds = intent.getIntArrayExtra(AppWidgetManager.EXTRA_APPWIDGET_OLD_IDS);
|
|
final int[] newIds = intent.getIntArrayExtra(AppWidgetManager.EXTRA_APPWIDGET_IDS);
|
|
if (oldIds != null && newIds != null && oldIds.length == newIds.length) {
|
|
RestoreDbTask.setRestoredAppWidgetIds(context, oldIds, newIds);
|
|
} else {
|
|
Log.e(TAG, "Invalid host restored received");
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Updates the app widgets whose id has changed during the restore process.
|
|
*/
|
|
@WorkerThread
|
|
public static void restoreAppWidgetIds(Context context, int[] oldWidgetIds, int[] newWidgetIds) {
|
|
AppWidgetHost appWidgetHost = new LauncherAppWidgetHost(context);
|
|
if (WidgetsModel.GO_DISABLE_WIDGETS) {
|
|
Log.e(TAG, "Skipping widget ID remap as widgets not supported");
|
|
appWidgetHost.deleteHost();
|
|
return;
|
|
}
|
|
if (!RestoreDbTask.isPending(context)) {
|
|
// Someone has already gone through our DB once, probably LoaderTask. Skip any further
|
|
// modifications of the DB.
|
|
Log.e(TAG, "Skipping widget ID remap as DB already in use");
|
|
for (int widgetId : newWidgetIds) {
|
|
Log.d(TAG, "Deleting widgetId: " + widgetId);
|
|
appWidgetHost.deleteAppWidgetId(widgetId);
|
|
}
|
|
return;
|
|
}
|
|
final ContentResolver cr = context.getContentResolver();
|
|
final AppWidgetManager widgets = AppWidgetManager.getInstance(context);
|
|
|
|
for (int i = 0; i < oldWidgetIds.length; i++) {
|
|
Log.i(TAG, "Widget state restore id " + oldWidgetIds[i] + " => " + newWidgetIds[i]);
|
|
|
|
final AppWidgetProviderInfo provider = widgets.getAppWidgetInfo(newWidgetIds[i]);
|
|
final int state;
|
|
if (LoaderTask.isValidProvider(provider)) {
|
|
// This will ensure that we show 'Click to setup' UI if required.
|
|
state = LauncherAppWidgetInfo.FLAG_UI_NOT_READY;
|
|
} else {
|
|
state = LauncherAppWidgetInfo.FLAG_PROVIDER_NOT_READY;
|
|
}
|
|
|
|
// b/135926478: Work profile widget restore is broken in platform. This forces us to
|
|
// recreate the widget during loading with the correct host provider.
|
|
long mainProfileId = UserCache.INSTANCE.get(context)
|
|
.getSerialNumberForUser(myUserHandle());
|
|
String oldWidgetId = Integer.toString(oldWidgetIds[i]);
|
|
final String where = "appWidgetId=? and (restored & 1) = 1 and profileId=?";
|
|
final String[] args = new String[] { oldWidgetId, Long.toString(mainProfileId) };
|
|
int result = new ContentWriter(context, new ContentWriter.CommitParams(where, args))
|
|
.put(LauncherSettings.Favorites.APPWIDGET_ID, newWidgetIds[i])
|
|
.put(LauncherSettings.Favorites.RESTORED, state)
|
|
.commit();
|
|
if (result == 0) {
|
|
Cursor cursor = cr.query(Favorites.CONTENT_URI,
|
|
new String[] {Favorites.APPWIDGET_ID},
|
|
"appWidgetId=?", new String[] { oldWidgetId }, null);
|
|
try {
|
|
if (!cursor.moveToFirst()) {
|
|
// The widget no long exists.
|
|
appWidgetHost.deleteAppWidgetId(newWidgetIds[i]);
|
|
}
|
|
} finally {
|
|
cursor.close();
|
|
}
|
|
}
|
|
// attempt to update widget id in backup table as well
|
|
new ContentWriter(context, ContentWriter.CommitParams.backupCommitParams(
|
|
"appWidgetId=? and profileId=?", args))
|
|
.put(LauncherSettings.Favorites.APPWIDGET_ID, newWidgetIds[i])
|
|
.put(LauncherSettings.Favorites.RESTORED, state)
|
|
.commit();
|
|
}
|
|
|
|
LauncherAppState app = LauncherAppState.getInstanceNoCreate();
|
|
if (app != null) {
|
|
app.getModel().forceReload();
|
|
}
|
|
}
|
|
}
|