Extending the grid migration logic to handle density changes
For hotseat migratino, we simply drop the items with least weight If the workspace row/column decreases by 2 or more, we clear the whole workspace Bug: 25958224 Change-Id: I7131b955023d185ed10955f593184b9238546dc8
This commit is contained in:
@@ -73,12 +73,12 @@ public class InvariantDeviceProfile {
|
||||
/**
|
||||
* Number of icons inside the hotseat area.
|
||||
*/
|
||||
int numHotseatIcons;
|
||||
public int numHotseatIcons;
|
||||
float hotseatIconSize;
|
||||
int defaultLayoutId;
|
||||
|
||||
// Derived invariant properties
|
||||
int hotseatAllAppsRank;
|
||||
public int hotseatAllAppsRank;
|
||||
|
||||
DeviceProfile landscapeProfile;
|
||||
DeviceProfile portraitProfile;
|
||||
|
||||
@@ -24,7 +24,7 @@ import android.database.Cursor;
|
||||
import android.os.ParcelFileDescriptor;
|
||||
import android.util.Log;
|
||||
|
||||
import com.android.launcher3.model.MigrateFromRestoreTask;
|
||||
import com.android.launcher3.model.GridSizeMigrationTask;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
@@ -101,8 +101,9 @@ public class LauncherBackupAgentHelper extends BackupAgentHelper {
|
||||
LauncherSettings.Settings.METHOD_UPDATE_FOLDER_ITEMS_RANK);
|
||||
}
|
||||
|
||||
if (MigrateFromRestoreTask.ENABLED && mHelper.shouldAttemptWorkspaceMigration()) {
|
||||
MigrateFromRestoreTask.markForMigration(getApplicationContext(),
|
||||
// TODO: Update this logic to handle grid difference of 2. as well as hotseat difference
|
||||
if (GridSizeMigrationTask.ENABLED && mHelper.shouldAttemptWorkspaceMigration()) {
|
||||
GridSizeMigrationTask.markForMigration(getApplicationContext(),
|
||||
(int) mHelper.migrationCompatibleProfileData.desktopCols,
|
||||
(int) mHelper.migrationCompatibleProfileData.desktopRows,
|
||||
mHelper.widgetSizes);
|
||||
|
||||
@@ -52,7 +52,7 @@ import com.android.launcher3.backup.BackupProtos.Screen;
|
||||
import com.android.launcher3.backup.BackupProtos.Widget;
|
||||
import com.android.launcher3.compat.UserHandleCompat;
|
||||
import com.android.launcher3.compat.UserManagerCompat;
|
||||
import com.android.launcher3.model.MigrateFromRestoreTask;
|
||||
import com.android.launcher3.model.GridSizeMigrationTask;
|
||||
import com.android.launcher3.util.Thunk;
|
||||
import com.google.protobuf.nano.InvalidProtocolBufferNanoException;
|
||||
import com.google.protobuf.nano.MessageNano;
|
||||
@@ -315,7 +315,7 @@ public class LauncherBackupHelper implements BackupHelper {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (MigrateFromRestoreTask.ENABLED &&
|
||||
if (GridSizeMigrationTask.ENABLED &&
|
||||
(oldProfile.desktopCols - currentProfile.desktopCols <= 1) &&
|
||||
(oldProfile.desktopRows - currentProfile.desktopRows <= 1)) {
|
||||
// Allow desktop migration when row and/or column count contracts by 1.
|
||||
|
||||
@@ -57,7 +57,7 @@ import com.android.launcher3.compat.PackageInstallerCompat.PackageInstallInfo;
|
||||
import com.android.launcher3.compat.UserHandleCompat;
|
||||
import com.android.launcher3.compat.UserManagerCompat;
|
||||
import com.android.launcher3.config.ProviderConfig;
|
||||
import com.android.launcher3.model.MigrateFromRestoreTask;
|
||||
import com.android.launcher3.model.GridSizeMigrationTask;
|
||||
import com.android.launcher3.model.WidgetsModel;
|
||||
import com.android.launcher3.util.ComponentKey;
|
||||
import com.android.launcher3.util.CursorIconInfo;
|
||||
@@ -1651,14 +1651,14 @@ public class LauncherModel extends BroadcastReceiver
|
||||
int countX = profile.numColumns;
|
||||
int countY = profile.numRows;
|
||||
|
||||
if (MigrateFromRestoreTask.ENABLED && MigrateFromRestoreTask.shouldRunTask(mContext)) {
|
||||
if (GridSizeMigrationTask.ENABLED && GridSizeMigrationTask.shouldRunTask(mContext)) {
|
||||
long migrationStartTime = System.currentTimeMillis();
|
||||
Log.v(TAG, "Starting workspace migration after restore");
|
||||
try {
|
||||
MigrateFromRestoreTask task = new MigrateFromRestoreTask(mContext);
|
||||
GridSizeMigrationTask task = new GridSizeMigrationTask(mContext);
|
||||
// Clear the flags before starting the task, so that we do not run the task
|
||||
// again, in case there was an uncaught error.
|
||||
MigrateFromRestoreTask.clearFlags(mContext);
|
||||
GridSizeMigrationTask.clearFlags(mContext);
|
||||
task.execute();
|
||||
} catch (Exception e) {
|
||||
Log.e(TAG, "Error during grid migration", e);
|
||||
@@ -1668,6 +1668,8 @@ public class LauncherModel extends BroadcastReceiver
|
||||
}
|
||||
Log.v(TAG, "Workspace migration completed in "
|
||||
+ (System.currentTimeMillis() - migrationStartTime));
|
||||
|
||||
GridSizeMigrationTask.saveCurrentConfig(mContext);
|
||||
}
|
||||
|
||||
if ((mFlags & LOADER_FLAG_CLEAR_WORKSPACE) != 0) {
|
||||
|
||||
+216
-44
@@ -24,29 +24,33 @@ import com.android.launcher3.Utilities;
|
||||
import com.android.launcher3.compat.PackageInstallerCompat;
|
||||
import com.android.launcher3.compat.UserHandleCompat;
|
||||
import com.android.launcher3.util.LongArrayMap;
|
||||
import com.android.launcher3.util.Thunk;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Locale;
|
||||
|
||||
/**
|
||||
* This class takes care of shrinking the workspace (by maximum of one row and one column), as a
|
||||
* result of restoring from a larger device.
|
||||
* result of restoring from a larger device or device density change.
|
||||
*/
|
||||
public class MigrateFromRestoreTask {
|
||||
public class GridSizeMigrationTask {
|
||||
|
||||
public static boolean ENABLED = false;
|
||||
public static boolean ENABLED = Utilities.isNycOrAbove();
|
||||
|
||||
private static final String TAG = "MigrateFromRestoreTask";
|
||||
private static final String TAG = "GridSizeMigrationTask";
|
||||
private static final boolean DEBUG = true;
|
||||
|
||||
private static final String KEY_MIGRATION_SOURCE_SIZE = "migration_restore_src_size";
|
||||
private static final String KEY_MIGRATION_SRC_WORKSPACE_SIZE = "migration_src_workspace_size";
|
||||
private static final String KEY_MIGRATION_SRC_HOTSEAT_SIZE = "migration_src_hotseat_size";
|
||||
|
||||
// Set of entries indicating minimum size a widget can be resized to. This is used during
|
||||
// restore in case the widget has not been installed yet.
|
||||
private static final String KEY_MIGRATION_WIDGET_MINSIZE = "migration_widget_min_size";
|
||||
|
||||
// These are carefully selected weights for various item types (Math.random?), to allow for
|
||||
// the lease absurd migration experience.
|
||||
// the least absurd migration experience.
|
||||
private static final float WT_SHORTCUT = 1;
|
||||
private static final float WT_APPLICATION = 0.8f;
|
||||
private static final float WT_WIDGET_MIN = 2;
|
||||
@@ -65,17 +69,37 @@ public class MigrateFromRestoreTask {
|
||||
private ArrayList<DbEntry> mCarryOver;
|
||||
|
||||
private final int mSrcX, mSrcY;
|
||||
@Thunk final int mTrgX, mTrgY;
|
||||
private final int mTrgX, mTrgY;
|
||||
private final boolean mShouldRemoveX, mShouldRemoveY;
|
||||
|
||||
public MigrateFromRestoreTask(Context context) {
|
||||
private final int mSrcHotseatSize;
|
||||
private final int mSrcAllAppsRank;
|
||||
|
||||
/**
|
||||
* TODO: Create a generic constructor which can be unit tested.
|
||||
*/
|
||||
public GridSizeMigrationTask(Context context) {
|
||||
mContext = context;
|
||||
|
||||
|
||||
mIdp = LauncherAppState.getInstance().getInvariantDeviceProfile();
|
||||
mTrgX = mIdp.numColumns;
|
||||
mTrgY = mIdp.numRows;
|
||||
|
||||
SharedPreferences prefs = Utilities.getPrefs(context);
|
||||
Point sourceSize = parsePoint(prefs.getString(KEY_MIGRATION_SOURCE_SIZE, ""));
|
||||
Point sourceSize = parsePoint(
|
||||
prefs.getString(KEY_MIGRATION_SRC_WORKSPACE_SIZE, getPointString(mTrgX, mTrgY)));
|
||||
mSrcX = sourceSize.x;
|
||||
mSrcY = sourceSize.y;
|
||||
|
||||
// Hotseat
|
||||
Point hotseatSize = parsePoint(
|
||||
prefs.getString(KEY_MIGRATION_SRC_HOTSEAT_SIZE,
|
||||
getPointString(mIdp.numHotseatIcons, mIdp.hotseatAllAppsRank)));
|
||||
mSrcHotseatSize = hotseatSize.x;
|
||||
mSrcAllAppsRank = hotseatSize.y;
|
||||
|
||||
// Widget sizes
|
||||
mWidgetMinSize = new HashMap<String, Point>();
|
||||
for (String s : prefs.getStringSet(KEY_MIGRATION_WIDGET_MINSIZE,
|
||||
Collections.<String>emptySet())) {
|
||||
@@ -83,16 +107,12 @@ public class MigrateFromRestoreTask {
|
||||
mWidgetMinSize.put(parts[0], parsePoint(parts[1]));
|
||||
}
|
||||
|
||||
mIdp = LauncherAppState.getInstance().getInvariantDeviceProfile();
|
||||
mTrgX = mIdp.numColumns;
|
||||
mTrgY = mIdp.numRows;
|
||||
mShouldRemoveX = mTrgX < mSrcX;
|
||||
mShouldRemoveY = mTrgY < mSrcY;
|
||||
}
|
||||
|
||||
public void execute() throws Exception {
|
||||
mEntryToRemove = new ArrayList<>();
|
||||
mCarryOver = new ArrayList<>();
|
||||
mUpdateOperations = new ArrayList<>();
|
||||
|
||||
// Initialize list of valid packages. This contain all the packages which are already on
|
||||
@@ -107,6 +127,97 @@ public class MigrateFromRestoreTask {
|
||||
mValidPackages.addAll(PackageInstallerCompat.getInstance(mContext)
|
||||
.updateAndGetActiveSessionCache().keySet());
|
||||
|
||||
// Migrate hotseat
|
||||
if (mSrcHotseatSize != mIdp.numHotseatIcons || mSrcAllAppsRank != mIdp.hotseatAllAppsRank) {
|
||||
migrateHotseat();
|
||||
}
|
||||
|
||||
if (mShouldRemoveX || mShouldRemoveY) {
|
||||
if ((mSrcY - mTrgX) > 1 || (mSrcY - mSrcY) > 1) {
|
||||
// TODO: support this.
|
||||
throw new Exception("The universe is too large for migration");
|
||||
} else {
|
||||
migrateWorkspace();
|
||||
}
|
||||
}
|
||||
|
||||
// Update items
|
||||
if (!mUpdateOperations.isEmpty()) {
|
||||
mContext.getContentResolver().applyBatch(LauncherProvider.AUTHORITY, mUpdateOperations);
|
||||
}
|
||||
|
||||
if (!mEntryToRemove.isEmpty()) {
|
||||
if (DEBUG) {
|
||||
Log.d(TAG, "Removing items: " + TextUtils.join(", ", mEntryToRemove));
|
||||
}
|
||||
mContext.getContentResolver().delete(LauncherSettings.Favorites.CONTENT_URI,
|
||||
Utilities.createDbSelectionQuery(
|
||||
LauncherSettings.Favorites._ID, mEntryToRemove), null);
|
||||
}
|
||||
|
||||
if (!mUpdateOperations.isEmpty() || !mEntryToRemove.isEmpty()) {
|
||||
// Make sure we haven't removed everything.
|
||||
final Cursor c = mContext.getContentResolver().query(
|
||||
LauncherSettings.Favorites.CONTENT_URI, null, null, null, null);
|
||||
boolean hasData = c.moveToNext();
|
||||
c.close();
|
||||
if (!hasData) {
|
||||
throw new Exception("Removed every thing during grid resize");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* To migrate hotseat, we load all the entries in order (LTR or RTL) and arrange them
|
||||
* in the order in the new hotseat while keeping an empty space for all-apps. If the number of
|
||||
* entries is more than what can fit in the new hotseat, we drop the entries with least weight.
|
||||
* For weight calculation {@see #WT_SHORTCUT}, {@see #WT_APPLICATION}
|
||||
* & {@see #WT_FOLDER_FACTOR}.
|
||||
*/
|
||||
private void migrateHotseat() {
|
||||
ArrayList<DbEntry> items = loadHotseatEntries();
|
||||
|
||||
int requiredCount = mIdp.numHotseatIcons - 1;
|
||||
|
||||
while (items.size() > requiredCount) {
|
||||
// Pick the center item by default.
|
||||
DbEntry toRemove = items.get(items.size() / 2);
|
||||
|
||||
// Find the item with least weight.
|
||||
for (DbEntry entry : items) {
|
||||
if (entry.weight < toRemove.weight) {
|
||||
toRemove = entry;
|
||||
}
|
||||
}
|
||||
|
||||
mEntryToRemove.add(toRemove.id);
|
||||
items.remove(toRemove);
|
||||
}
|
||||
|
||||
// Update screen IDS
|
||||
int newScreenId = 0;
|
||||
for (DbEntry entry : items) {
|
||||
if (entry.screenId != newScreenId) {
|
||||
entry.screenId = newScreenId;
|
||||
|
||||
// These values does not affect the item position, but we should set them
|
||||
// to something other than -1.
|
||||
entry.cellX = newScreenId;
|
||||
entry.cellY = 0;
|
||||
|
||||
update(entry);
|
||||
}
|
||||
|
||||
newScreenId++;
|
||||
if (newScreenId == mIdp.hotseatAllAppsRank) {
|
||||
newScreenId++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void migrateWorkspace() throws Exception {
|
||||
mCarryOver = new ArrayList<>();
|
||||
|
||||
ArrayList<Long> allScreens = LauncherModel.loadWorkspaceScreensDb(mContext);
|
||||
if (allScreens.isEmpty()) {
|
||||
throw new Exception("Unable to get workspace screens");
|
||||
@@ -157,27 +268,6 @@ public class MigrateFromRestoreTask {
|
||||
LauncherAppState.getInstance().getModel()
|
||||
.updateWorkspaceScreenOrder(mContext, allScreens);
|
||||
}
|
||||
|
||||
// Update items
|
||||
mContext.getContentResolver().applyBatch(LauncherProvider.AUTHORITY, mUpdateOperations);
|
||||
|
||||
if (!mEntryToRemove.isEmpty()) {
|
||||
if (DEBUG) {
|
||||
Log.d(TAG, "Removing items: " + TextUtils.join(", ", mEntryToRemove));
|
||||
}
|
||||
mContext.getContentResolver().delete(LauncherSettings.Favorites.CONTENT_URI,
|
||||
Utilities.createDbSelectionQuery(
|
||||
LauncherSettings.Favorites._ID, mEntryToRemove), null);
|
||||
}
|
||||
|
||||
// Make sure we haven't removed everything.
|
||||
final Cursor c = mContext.getContentResolver().query(
|
||||
LauncherSettings.Favorites.CONTENT_URI, null, null, null, null);
|
||||
boolean hasData = c.moveToNext();
|
||||
c.close();
|
||||
if (!hasData) {
|
||||
throw new Exception("Removed every thing during grid resize");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -191,7 +281,7 @@ public class MigrateFromRestoreTask {
|
||||
* (otherwise they are placed on a new screen).
|
||||
*/
|
||||
private void migrateScreen(long screenId) {
|
||||
ArrayList<DbEntry> items = loadEntries(screenId);
|
||||
ArrayList<DbEntry> items = loadWorkspaceEntries(screenId);
|
||||
|
||||
int removedCol = Integer.MAX_VALUE;
|
||||
int removedRow = Integer.MAX_VALUE;
|
||||
@@ -329,7 +419,7 @@ public class MigrateFromRestoreTask {
|
||||
return finalItems;
|
||||
}
|
||||
|
||||
@Thunk void markCells(boolean[][] occupied, DbEntry item, boolean val) {
|
||||
private void markCells(boolean[][] occupied, DbEntry item, boolean val) {
|
||||
for (int i = item.cellX; i < (item.cellX + item.spanX); i++) {
|
||||
for (int j = item.cellY; j < (item.cellY + item.spanY); j++) {
|
||||
occupied[i][j] = val;
|
||||
@@ -337,7 +427,7 @@ public class MigrateFromRestoreTask {
|
||||
}
|
||||
}
|
||||
|
||||
@Thunk boolean isVacant(boolean[][] occupied, int x, int y, int w, int h) {
|
||||
private boolean isVacant(boolean[][] occupied, int x, int y, int w, int h) {
|
||||
if (x + w > mTrgX) return false;
|
||||
if (y + h > mTrgY) return false;
|
||||
|
||||
@@ -545,10 +635,71 @@ public class MigrateFromRestoreTask {
|
||||
}
|
||||
}
|
||||
|
||||
private ArrayList<DbEntry> loadHotseatEntries() {
|
||||
Cursor c = mContext.getContentResolver().query(LauncherSettings.Favorites.CONTENT_URI,
|
||||
new String[]{
|
||||
Favorites._ID, // 0
|
||||
Favorites.ITEM_TYPE, // 1
|
||||
Favorites.INTENT, // 2
|
||||
Favorites.SCREEN}, // 3
|
||||
Favorites.CONTAINER + " = " + Favorites.CONTAINER_HOTSEAT, null, null, null);
|
||||
|
||||
final int indexId = c.getColumnIndexOrThrow(Favorites._ID);
|
||||
final int indexItemType = c.getColumnIndexOrThrow(Favorites.ITEM_TYPE);
|
||||
final int indexIntent = c.getColumnIndexOrThrow(Favorites.INTENT);
|
||||
final int indexScreen = c.getColumnIndexOrThrow(Favorites.SCREEN);
|
||||
|
||||
ArrayList<DbEntry> entries = new ArrayList<>();
|
||||
while (c.moveToNext()) {
|
||||
DbEntry entry = new DbEntry();
|
||||
entry.id = c.getLong(indexId);
|
||||
entry.itemType = c.getInt(indexItemType);
|
||||
entry.screenId = c.getLong(indexScreen);
|
||||
|
||||
if (entry.screenId >= mSrcHotseatSize) {
|
||||
mEntryToRemove.add(entry.id);
|
||||
continue;
|
||||
}
|
||||
|
||||
try {
|
||||
// calculate weight
|
||||
switch (entry.itemType) {
|
||||
case Favorites.ITEM_TYPE_SHORTCUT:
|
||||
case Favorites.ITEM_TYPE_APPLICATION: {
|
||||
verifyIntent(c.getString(indexIntent));
|
||||
entry.weight = entry.itemType == Favorites.ITEM_TYPE_SHORTCUT
|
||||
? WT_SHORTCUT : WT_APPLICATION;
|
||||
break;
|
||||
}
|
||||
case Favorites.ITEM_TYPE_FOLDER: {
|
||||
int total = getFolderItemsCount(entry.id);
|
||||
if (total == 0) {
|
||||
throw new Exception("Folder is empty");
|
||||
}
|
||||
entry.weight = WT_FOLDER_FACTOR * total;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
throw new Exception("Invalid item type");
|
||||
}
|
||||
} catch (Exception e) {
|
||||
if (DEBUG) {
|
||||
Log.d(TAG, "Removing item " + entry.id, e);
|
||||
}
|
||||
mEntryToRemove.add(entry.id);
|
||||
continue;
|
||||
}
|
||||
entries.add(entry);
|
||||
}
|
||||
c.close();
|
||||
return entries;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Loads entries for a particular screen id.
|
||||
*/
|
||||
public ArrayList<DbEntry> loadEntries(long screen) {
|
||||
private ArrayList<DbEntry> loadWorkspaceEntries(long screen) {
|
||||
Cursor c = mContext.getContentResolver().query(LauncherSettings.Favorites.CONTENT_URI,
|
||||
new String[] {
|
||||
Favorites._ID, // 0
|
||||
@@ -733,7 +884,7 @@ public class MigrateFromRestoreTask {
|
||||
}
|
||||
}
|
||||
|
||||
@Thunk static ArrayList<DbEntry> deepCopy(ArrayList<DbEntry> src) {
|
||||
private static ArrayList<DbEntry> deepCopy(ArrayList<DbEntry> src) {
|
||||
ArrayList<DbEntry> dup = new ArrayList<DbEntry>(src.size());
|
||||
for (DbEntry e : src) {
|
||||
dup.add(e.copy());
|
||||
@@ -749,18 +900,39 @@ public class MigrateFromRestoreTask {
|
||||
public static void markForMigration(Context context, int srcX, int srcY,
|
||||
HashSet<String> widgets) {
|
||||
Utilities.getPrefs(context).edit()
|
||||
.putString(KEY_MIGRATION_SOURCE_SIZE, srcX + "," + srcY)
|
||||
.putString(KEY_MIGRATION_SRC_WORKSPACE_SIZE, getPointString(srcX, srcY))
|
||||
.putStringSet(KEY_MIGRATION_WIDGET_MINSIZE, widgets)
|
||||
.apply();
|
||||
}
|
||||
|
||||
public static boolean shouldRunTask(Context context) {
|
||||
return !TextUtils.isEmpty(Utilities.getPrefs(context).getString(KEY_MIGRATION_SOURCE_SIZE, ""));
|
||||
SharedPreferences prefs = Utilities.getPrefs(context);
|
||||
InvariantDeviceProfile idp = LauncherAppState.getInstance().getInvariantDeviceProfile();
|
||||
|
||||
// Run task if workspace or hotseat size has changed.
|
||||
return !getPointString(idp.numColumns, idp.numRows).equals(
|
||||
prefs.getString(KEY_MIGRATION_SRC_WORKSPACE_SIZE, ""))
|
||||
|| !getPointString(idp.numHotseatIcons, idp.hotseatAllAppsRank).equals(
|
||||
prefs.getString(KEY_MIGRATION_SRC_HOTSEAT_SIZE, ""));
|
||||
}
|
||||
|
||||
public static void clearFlags(Context context) {
|
||||
Utilities.getPrefs(context).edit().remove(KEY_MIGRATION_SOURCE_SIZE)
|
||||
.remove(KEY_MIGRATION_WIDGET_MINSIZE).commit();
|
||||
Utilities.getPrefs(context).edit().remove(KEY_MIGRATION_WIDGET_MINSIZE).commit();
|
||||
}
|
||||
|
||||
public static void saveCurrentConfig(Context context) {
|
||||
InvariantDeviceProfile idp = LauncherAppState.getInstance().getInvariantDeviceProfile();
|
||||
Utilities.getPrefs(context).edit()
|
||||
.putString(KEY_MIGRATION_SRC_WORKSPACE_SIZE,
|
||||
getPointString(idp.numColumns, idp.numRows))
|
||||
.putString(KEY_MIGRATION_SRC_HOTSEAT_SIZE,
|
||||
getPointString(idp.numHotseatIcons, idp.hotseatAllAppsRank))
|
||||
.remove(KEY_MIGRATION_WIDGET_MINSIZE)
|
||||
.commit();
|
||||
}
|
||||
|
||||
private static String getPointString(int x, int y) {
|
||||
return String.format(Locale.ENGLISH, "%d,%d", x, y);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -23,26 +23,30 @@ import android.content.IntentFilter;
|
||||
import android.content.res.Configuration;
|
||||
import android.util.Log;
|
||||
|
||||
import com.android.launcher3.Utilities;
|
||||
|
||||
/**
|
||||
* {@link BroadcastReceiver} which watches configuration changes and
|
||||
* restarts the process in case changes which affect the device profile.
|
||||
* restarts the process in case changes which affect the device profile occur.
|
||||
*/
|
||||
public class ConfigMonitor extends BroadcastReceiver {
|
||||
|
||||
private final Context mContext;
|
||||
private final float mFontScale;
|
||||
private final int mDensity;
|
||||
|
||||
public ConfigMonitor(Context context) {
|
||||
mContext = context;
|
||||
|
||||
Configuration config = context.getResources().getConfiguration();
|
||||
mFontScale = config.fontScale;
|
||||
mDensity = getDensity(config);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onReceive(Context context, Intent intent) {
|
||||
Configuration config = context.getResources().getConfiguration();
|
||||
if (mFontScale != config.fontScale) {
|
||||
if (mFontScale != config.fontScale || mDensity != getDensity(config)) {
|
||||
Log.d("ConfigMonitor", "Configuration changed, restarting launcher");
|
||||
mContext.unregisterReceiver(this);
|
||||
android.os.Process.killProcess(android.os.Process.myPid());
|
||||
@@ -52,4 +56,8 @@ public class ConfigMonitor extends BroadcastReceiver {
|
||||
public void register() {
|
||||
mContext.registerReceiver(this, new IntentFilter(Intent.ACTION_CONFIGURATION_CHANGED));
|
||||
}
|
||||
|
||||
private static int getDensity(Configuration config) {
|
||||
return Utilities.ATLEAST_JB_MR1 ? config.densityDpi : 0;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user