Merge "Don't obfuscate Launcher3" into ub-launcher3-burnaby
diff --git a/Android.mk b/Android.mk
index 2e57478..3ff542e 100644
--- a/Android.mk
+++ b/Android.mk
@@ -36,7 +36,7 @@
LOCAL_SDK_VERSION := current
LOCAL_PACKAGE_NAME := Launcher3
-LOCAL_OVERRIDES_PACKAGES := Launcher2
+LOCAL_OVERRIDES_PACKAGES := Home Launcher2
include $(BUILD_PACKAGE)
diff --git a/protos/backup.proto b/protos/backup.proto
index 09330ee..d8d94e8 100644
--- a/protos/backup.proto
+++ b/protos/backup.proto
@@ -102,17 +102,17 @@
optional string iconResource = 17;
optional bytes icon = 18;
optional TargetType targetType = 19 [default = TARGET_NONE];
- }
+}
message Screen {
required int64 id = 1;
optional int32 rank = 2;
- }
+}
message Resource {
required int32 dpi = 1;
required bytes data = 2;
- }
+}
message Widget {
required string provider = 1;
@@ -120,4 +120,8 @@
optional bool configure = 3;
optional Resource icon = 4;
optional Resource preview = 5;
- }
+
+ // Assume that a widget is resizable upto 2x2 if no data is available
+ optional int32 minSpanX = 6 [default = 2];
+ optional int32 minSpanY = 7 [default = 2];
+}
diff --git a/res/layout-sw720dp/launcher.xml b/res/layout-sw720dp/launcher.xml
index d382c6a..802922e 100644
--- a/res/layout-sw720dp/launcher.xml
+++ b/res/layout-sw720dp/launcher.xml
@@ -18,7 +18,6 @@
<com.android.launcher3.LauncherRootView
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:launcher="http://schemas.android.com/apk/res-auto"
-
android:id="@+id/launcher"
android:layout_width="match_parent"
android:layout_height="match_parent"
diff --git a/res/values-gu-rIN/strings.xml b/res/values-gu-rIN/strings.xml
index b547db4..4a2274f 100644
--- a/res/values-gu-rIN/strings.xml
+++ b/res/values-gu-rIN/strings.xml
@@ -26,15 +26,15 @@
<string name="activity_not_available" msgid="7456344436509528827">"એપ્લિકેશન ઉપલબ્ધ નથી"</string>
<string name="safemode_shortcut_error" msgid="9160126848219158407">"સુરક્ષિત મોડમાં ડાઉનલોડ કરેલ એપ્લિકેશન અક્ષમ કરી"</string>
<string name="safemode_widget_error" msgid="4863470563535682004">"સુરક્ષિત મોડમાં વિજેટ્સ અક્ષમ કર્યા"</string>
- <string name="toggle_weight_watcher" msgid="5645299835184636119">"Mem દર્શાવો"</string>
+ <string name="toggle_weight_watcher" msgid="5645299835184636119">"Mem બતાવો"</string>
<string name="long_press_widget_to_add" msgid="7699152356777458215">"વિજેટ ચૂંટવા માટે ટચ કરો અને પકડી રાખો."</string>
<string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
- <string name="all_apps_search_bar_hint" msgid="7084713969757597256">"શોધ એપ્લિકેશન્સ"</string>
- <string name="all_apps_loading_message" msgid="7557140873644765180">"એપ્લિકેશન્સ લોડ કરી રહ્યું છે…"</string>
- <string name="all_apps_no_search_results" msgid="6332185285860416787">"\"<xliff:g id="QUERY">%1$s</xliff:g>\" થી મેળ ખાતી કોઈ એપ્લિકેશન્સ મળી નથી"</string>
+ <string name="all_apps_search_bar_hint" msgid="7084713969757597256">"શોધ એપ્લિકેશનો"</string>
+ <string name="all_apps_loading_message" msgid="7557140873644765180">"એપ્લિકેશનો લોડ કરી રહ્યું છે…"</string>
+ <string name="all_apps_no_search_results" msgid="6332185285860416787">"\"<xliff:g id="QUERY">%1$s</xliff:g>\" થી મેળ ખાતી કોઈ એપ્લિકેશનો મળી નથી"</string>
<string name="out_of_space" msgid="4691004494942118364">"આ હોમ સ્ક્રીન પર વધુ જગ્યા નથી."</string>
<string name="hotseat_out_of_space" msgid="7448809638125333693">"મનપસંદ ટ્રે પર વધુ જગ્યા નથી"</string>
- <string name="all_apps_button_label" msgid="9110807029020582876">"એપ્લિકેશન્સ"</string>
+ <string name="all_apps_button_label" msgid="9110807029020582876">"એપ્લિકેશનો"</string>
<string name="all_apps_home_button_label" msgid="252062713717058851">"હોમ"</string>
<string name="delete_target_label" msgid="1822697352535677073">"દૂર કરો"</string>
<string name="delete_target_uninstall_label" msgid="5100785476250872595">"અનઇન્સ્ટોલ કરો"</string>
diff --git a/res/values-ml-rIN/strings.xml b/res/values-ml-rIN/strings.xml
index 71a9e36..59ad153 100644
--- a/res/values-ml-rIN/strings.xml
+++ b/res/values-ml-rIN/strings.xml
@@ -38,7 +38,7 @@
<string name="all_apps_home_button_label" msgid="252062713717058851">"ഹോം"</string>
<string name="delete_target_label" msgid="1822697352535677073">"നീക്കംചെയ്യുക"</string>
<string name="delete_target_uninstall_label" msgid="5100785476250872595">"അണ്ഇസ്റ്റാളുചെയ്യുക"</string>
- <string name="info_target_label" msgid="8053346143994679532">"അപ്ലിക്കേഷൻ വിവരം"</string>
+ <string name="info_target_label" msgid="8053346143994679532">"ആപ്പ് വിവരം"</string>
<string name="permlab_install_shortcut" msgid="5632423390354674437">"കുറുക്കുവഴികൾ ഇൻസ്റ്റാളുചെയ്യുക"</string>
<string name="permdesc_install_shortcut" msgid="923466509822011139">"ഉപയോക്തൃ ഇടപെടൽ ഇല്ലാതെ കുറുക്കുവഴികൾ ചേർക്കാൻ അപ്ലിക്കേഷനെ അനുവദിക്കുന്നു."</string>
<string name="permlab_read_settings" msgid="1941457408239617576">"ഹോം ക്രമീകരണങ്ങളും കുറുക്കുവഴികളും റീഡുചെയ്യുക"</string>
diff --git a/res/values-ta-rIN/strings.xml b/res/values-ta-rIN/strings.xml
index e2b680a..1f2a6f9 100644
--- a/res/values-ta-rIN/strings.xml
+++ b/res/values-ta-rIN/strings.xml
@@ -51,7 +51,7 @@
<string name="folder_hint_text" msgid="6617836969016293992">"பெயரிடப்படாத கோப்புறை"</string>
<string name="default_scroll_format" msgid="7475544710230993317">"பக்கம் %1$d / %2$d"</string>
<string name="workspace_scroll_format" msgid="8458889198184077399">"முகப்புத் திரை %1$d of %2$d"</string>
- <string name="first_run_cling_title" msgid="2459738000155917941">"வரவேற்கிறோம்"</string>
+ <string name="first_run_cling_title" msgid="2459738000155917941">"நல்வரவு"</string>
<string name="migration_cling_title" msgid="9181776667882933767">"பயன்பாட்டின் ஐகான்களை நகலெடுக்கவும்"</string>
<string name="migration_cling_description" msgid="2752413805582227644">"பழைய முகப்புத் திரைகளிலிருந்து ஐகான்களையும் கோப்புறைகளையும் இறக்குமதி செய்யவா?"</string>
<string name="migration_cling_copy_apps" msgid="946331230090919440">"ஐகான்களை நகலெடு"</string>
diff --git a/src/com/android/launcher3/CellLayout.java b/src/com/android/launcher3/CellLayout.java
index 2cde3d5..8096887 100644
--- a/src/com/android/launcher3/CellLayout.java
+++ b/src/com/android/launcher3/CellLayout.java
@@ -2690,8 +2690,12 @@
* @param result An array of length 2 in which to store the result (may be null).
*/
public static int[] rectToCell(Launcher launcher, int width, int height, int[] result) {
- DeviceProfile grid = launcher.getDeviceProfile();
- Rect padding = grid.getWorkspacePadding(Utilities.isRtl(launcher.getResources()));
+ return rectToCell(launcher.getDeviceProfile(), launcher, width, height, result);
+ }
+
+ public static int[] rectToCell(DeviceProfile grid, Context context, int width, int height,
+ int[] result) {
+ Rect padding = grid.getWorkspacePadding(Utilities.isRtl(context.getResources()));
// Always assume we're working with the smallest span to make sure we
// reserve enough space in both orientations.
diff --git a/src/com/android/launcher3/DeviceProfile.java b/src/com/android/launcher3/DeviceProfile.java
index a50540d..62b05b0 100644
--- a/src/com/android/launcher3/DeviceProfile.java
+++ b/src/com/android/launcher3/DeviceProfile.java
@@ -265,7 +265,7 @@
if (isTablet) {
// Pad the left and right of the workspace to ensure consistent spacing
// between all icons
- int width = isLandscape ? Math.max(widthPx, heightPx) : Math.min(widthPx, heightPx);
+ int width = getCurrentWidth();
// XXX: If the icon size changes across orientations, we will have to take
// that into account here too.
int gap = (int) ((width - 2 * edgeMarginPx -
@@ -301,12 +301,8 @@
// Pad the left and right of the workspace to ensure consistent spacing
// between all icons
float gapScale = 1f + (dragViewScale - 1f) / 2f;
- int width = isLandscape
- ? Math.max(widthPx, heightPx)
- : Math.min(widthPx, heightPx);
- int height = isLandscape
- ? Math.max(widthPx, heightPx)
- : Math.min(widthPx, heightPx);
+ int width = getCurrentWidth();
+ int height = getCurrentHeight();
int paddingTop = searchBarBounds.bottom;
int paddingBottom = hotseatBarHeightPx + pageIndicatorHeightPx;
int availableWidth = Math.max(0, width - (int) ((inv.numColumns * cellWidthPx) +
@@ -517,4 +513,16 @@
}
}
}
+
+ private int getCurrentWidth() {
+ return isLandscape
+ ? Math.max(widthPx, heightPx)
+ : Math.min(widthPx, heightPx);
+ }
+
+ private int getCurrentHeight() {
+ return isLandscape
+ ? Math.min(widthPx, heightPx)
+ : Math.max(widthPx, heightPx);
+ }
}
diff --git a/src/com/android/launcher3/IconCache.java b/src/com/android/launcher3/IconCache.java
index b9ac2a4..ea1c0fd 100644
--- a/src/com/android/launcher3/IconCache.java
+++ b/src/com/android/launcher3/IconCache.java
@@ -466,7 +466,7 @@
}
LauncherActivityInfoCompat launcherActInfo = mLauncherApps.resolveActivity(intent, user);
- CacheEntry entry = cacheLocked(component, launcherActInfo, user, true, true);
+ CacheEntry entry = cacheLocked(component, launcherActInfo, user, true, false /* useLowRes */);
return entry.icon;
}
@@ -540,7 +540,7 @@
mCache.put(cacheKey, entry);
// Check the DB first.
- if (!getEntryFromDB(componentName, user, entry, useLowResIcon)) {
+ if (!getEntryFromDB(cacheKey, entry, useLowResIcon)) {
if (info != null) {
entry.icon = Utilities.createIconBitmap(info.getBadgedIcon(mIconDpi), mContext);
} else {
@@ -579,7 +579,14 @@
Bitmap icon, CharSequence title) {
removeFromMemCacheLocked(packageName, user);
- CacheEntry entry = getEntryForPackageLocked(packageName, user, false);
+ ComponentKey cacheKey = getPackageKey(packageName, user);
+ CacheEntry entry = mCache.get(cacheKey);
+
+ // For icon caching, do not go through DB. Just update the in-memory entry.
+ if (entry == null) {
+ entry = new CacheEntry();
+ mCache.put(cacheKey, entry);
+ }
if (!TextUtils.isEmpty(title)) {
entry.title = title;
}
@@ -588,15 +595,18 @@
}
}
+ private static ComponentKey getPackageKey(String packageName, UserHandleCompat user) {
+ ComponentName cn = new ComponentName(packageName, packageName + EMPTY_CLASS_NAME);
+ return new ComponentKey(cn, user);
+ }
+
/**
* Gets an entry for the package, which can be used as a fallback entry for various components.
* This method is not thread safe, it must be called from a synchronized method.
- *
*/
private CacheEntry getEntryForPackageLocked(String packageName, UserHandleCompat user,
boolean useLowResIcon) {
- ComponentName cn = new ComponentName(packageName, packageName + EMPTY_CLASS_NAME);
- ComponentKey cacheKey = new ComponentKey(cn, user);
+ ComponentKey cacheKey = getPackageKey(packageName, user);
CacheEntry entry = mCache.get(cacheKey);
if (entry == null || (entry.isLowResIcon && !useLowResIcon)) {
@@ -604,7 +614,7 @@
boolean entryUpdated = true;
// Check the DB first.
- if (!getEntryFromDB(cn, user, entry, useLowResIcon)) {
+ if (!getEntryFromDB(cacheKey, entry, useLowResIcon)) {
try {
PackageInfo info = mPackageManager.getPackageInfo(packageName, 0);
ApplicationInfo appInfo = info.applicationInfo;
@@ -622,7 +632,8 @@
// package updates.
ContentValues values =
newContentValues(entry.icon, entry.title.toString(), mPackageBgColor);
- addIconToDB(values, cn, info, mUserManager.getSerialNumberForUser(user));
+ addIconToDB(values, cacheKey.componentName, info,
+ mUserManager.getSerialNumberForUser(user));
} catch (NameNotFoundException e) {
if (DEBUG) Log.d(TAG, "Application not installed " + packageName);
@@ -649,7 +660,7 @@
* @param dpi the native density of the icon
*/
public void preloadIcon(ComponentName componentName, Bitmap icon, int dpi, String label,
- long userSerial) {
+ long userSerial, InvariantDeviceProfile idp) {
// TODO rescale to the correct native DPI
try {
PackageManager packageManager = mContext.getPackageManager();
@@ -660,21 +671,22 @@
// pass
}
- ContentValues values = newContentValues(icon, label, Color.TRANSPARENT);
+ ContentValues values = newContentValues(
+ Bitmap.createScaledBitmap(icon, idp.iconBitmapSize, idp.iconBitmapSize, true),
+ label, Color.TRANSPARENT);
values.put(IconDB.COLUMN_COMPONENT, componentName.flattenToString());
values.put(IconDB.COLUMN_USER, userSerial);
mIconDb.getWritableDatabase().insertWithOnConflict(IconDB.TABLE_NAME, null, values,
SQLiteDatabase.CONFLICT_REPLACE);
}
- private boolean getEntryFromDB(ComponentName component, UserHandleCompat user,
- CacheEntry entry, boolean lowRes) {
+ private boolean getEntryFromDB(ComponentKey cacheKey, CacheEntry entry, boolean lowRes) {
Cursor c = mIconDb.getReadableDatabase().query(IconDB.TABLE_NAME,
new String[] {lowRes ? IconDB.COLUMN_ICON_LOW_RES : IconDB.COLUMN_ICON,
IconDB.COLUMN_LABEL},
IconDB.COLUMN_COMPONENT + " = ? AND " + IconDB.COLUMN_USER + " = ?",
- new String[] {component.flattenToString(),
- Long.toString(mUserManager.getSerialNumberForUser(user))},
+ new String[] {cacheKey.componentName.flattenToString(),
+ Long.toString(mUserManager.getSerialNumberForUser(cacheKey.user))},
null, null, null);
try {
if (c.moveToNext()) {
@@ -685,7 +697,8 @@
entry.title = "";
entry.contentDescription = "";
} else {
- entry.contentDescription = mUserManager.getBadgedLabelForUser(entry.title, user);
+ entry.contentDescription = mUserManager.getBadgedLabelForUser(
+ entry.title, cacheKey.user);
}
return true;
}
diff --git a/src/com/android/launcher3/Launcher.java b/src/com/android/launcher3/Launcher.java
index 339d5a3..6648b6e 100644
--- a/src/com/android/launcher3/Launcher.java
+++ b/src/com/android/launcher3/Launcher.java
@@ -263,6 +263,7 @@
private ViewGroup mOverviewPanel;
private View mAllAppsButton;
+ private View mWidgetsButton;
private SearchDropTargetBar mSearchDropTargetBar;
@@ -1370,8 +1371,8 @@
}
mOverviewPanel = (ViewGroup) findViewById(R.id.overview_panel);
- View widgetButton = findViewById(R.id.widget_button);
- widgetButton.setOnClickListener(new OnClickListener() {
+ mWidgetsButton = findViewById(R.id.widget_button);
+ mWidgetsButton.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View arg0) {
if (!mWorkspace.isSwitchingState()) {
@@ -1379,7 +1380,7 @@
}
}
});
- widgetButton.setOnTouchListener(getHapticFeedbackTouchListener());
+ mWidgetsButton.setOnTouchListener(getHapticFeedbackTouchListener());
View wallpaperButton = findViewById(R.id.wallpaper_button);
wallpaperButton.setOnClickListener(new OnClickListener() {
@@ -1465,6 +1466,10 @@
return mAllAppsButton;
}
+ public View getWidgetsButton() {
+ return mWidgetsButton;
+ }
+
/**
* Creates a view representing a shortcut.
*
diff --git a/src/com/android/launcher3/LauncherBackupAgentHelper.java b/src/com/android/launcher3/LauncherBackupAgentHelper.java
index e607a0f..a92a889 100644
--- a/src/com/android/launcher3/LauncherBackupAgentHelper.java
+++ b/src/com/android/launcher3/LauncherBackupAgentHelper.java
@@ -92,7 +92,7 @@
LauncherClings.synchonouslyMarkFirstRunClingDismissed(this);
// TODO: Update the backup set to include rank.
- if (mHelper.restoredBackupVersion <= 2) {
+ if (mHelper.restoredBackupVersion <= 3) {
LauncherAppState.getLauncherProvider().updateFolderItemsRank();
LauncherAppState.getLauncherProvider().convertShortcutsToLauncherActivities();
}
diff --git a/src/com/android/launcher3/LauncherBackupHelper.java b/src/com/android/launcher3/LauncherBackupHelper.java
index f209736..38a4bde 100644
--- a/src/com/android/launcher3/LauncherBackupHelper.java
+++ b/src/com/android/launcher3/LauncherBackupHelper.java
@@ -75,7 +75,7 @@
private static final boolean VERBOSE = LauncherBackupAgentHelper.VERBOSE;
private static final boolean DEBUG = LauncherBackupAgentHelper.DEBUG;
- private static final int BACKUP_VERSION = 2;
+ private static final int BACKUP_VERSION = 3;
private static final int MAX_JOURNAL_SIZE = 1000000;
// Journal key is such that it is always smaller than any dynamically generated
@@ -148,10 +148,15 @@
private IconCache mIconCache;
private DeviceProfieData mDeviceProfileData;
+ private InvariantDeviceProfile mIdp;
boolean restoreSuccessful;
int restoredBackupVersion = 1;
+ // When migrating from a device which different hotseat configuration, the icons are shifted
+ // to center along the new all-apps icon.
+ private int mHotseatShift = 0;
+
public LauncherBackupHelper(Context context) {
mContext = context;
mExistingKeys = new HashSet<String>();
@@ -178,6 +183,7 @@
mExistingKeys.add(keyToBackupKey(key));
}
}
+ restoredBackupVersion = journal.backupVersion;
}
/**
@@ -206,7 +212,8 @@
if (mDeviceProfileData == null) {
LauncherAppState app = LauncherAppState.getInstance();
- mDeviceProfileData = initDeviceProfileData(app.getInvariantDeviceProfile());
+ mIdp = app.getInvariantDeviceProfile();
+ mDeviceProfileData = initDeviceProfileData(mIdp);
mIconCache = app.getIconCache();
}
@@ -282,10 +289,15 @@
boolean isHotsetCompatible = false;
if (currentProfile.allappsRank >= oldProfile.hotseatCount) {
isHotsetCompatible = true;
+ mHotseatShift = 0;
}
- if ((currentProfile.hotseatCount >= oldProfile.hotseatCount) &&
- (currentProfile.allappsRank == oldProfile.allappsRank)) {
+
+ if ((currentProfile.allappsRank >= oldProfile.allappsRank)
+ && ((currentProfile.hotseatCount - currentProfile.allappsRank) >=
+ (oldProfile.hotseatCount - oldProfile.allappsRank))) {
+ // There is enough space on both sides of the hotseat.
isHotsetCompatible = true;
+ mHotseatShift = currentProfile.allappsRank - oldProfile.allappsRank;
}
return isHotsetCompatible && (currentProfile.desktopCols >= oldProfile.desktopCols)
@@ -308,9 +320,9 @@
if (mDeviceProfileData == null) {
// This call does not happen on a looper thread. So LauncherAppState
// can't be created . Instead initialize required dependencies directly.
- InvariantDeviceProfile profile = new InvariantDeviceProfile(mContext);
- mDeviceProfileData = initDeviceProfileData(profile);
- mIconCache = new IconCache(mContext, profile);
+ mIdp = new InvariantDeviceProfile(mContext);
+ mDeviceProfileData = initDeviceProfileData(mIdp);
+ mIconCache = new IconCache(mContext, mIdp);
}
int dataSize = data.size();
@@ -335,7 +347,6 @@
MessageNano.mergeFrom(journal, readCheckedBytes(mBuffer, dataSize));
applyJournal(journal);
restoreSuccessful = isBackupCompatible(journal);
- restoredBackupVersion = journal.backupVersion;
return;
}
@@ -599,10 +610,11 @@
Bitmap icon = BitmapFactory.decodeByteArray(res.data, 0, res.data.length);
if (icon == null) {
Log.w(TAG, "failed to unpack icon for " + key.name);
+ } else {
+ if (VERBOSE) Log.v(TAG, "saving restored icon as: " + key.name);
+ mIconCache.preloadIcon(ComponentName.unflattenFromString(key.name), icon, res.dpi,
+ "" /* label */, mUserSerial, mIdp);
}
- if (VERBOSE) Log.v(TAG, "saving restored icon as: " + key.name);
- mIconCache.preloadIcon(ComponentName.unflattenFromString(key.name), icon, res.dpi,
- "" /* label */, mUserSerial);
}
/**
@@ -636,7 +648,7 @@
} else {
Log.w(TAG, "empty intent on appwidget: " + id);
}
- if (mExistingKeys.contains(backupKey)) {
+ if (mExistingKeys.contains(backupKey) && restoredBackupVersion >= BACKUP_VERSION) {
if (DEBUG) Log.d(TAG, "already saved widget " + backupKey);
// remember that we already backed this up previously
@@ -683,7 +695,7 @@
Log.w(TAG, "failed to unpack widget icon for " + key.name);
} else {
mIconCache.preloadIcon(ComponentName.unflattenFromString(widget.provider),
- icon, widget.icon.dpi, widget.label, mUserSerial);
+ icon, widget.icon.dpi, widget.label, mUserSerial, mIdp);
}
}
@@ -845,6 +857,11 @@
throws IOException {
Favorite favorite = unpackProto(new Favorite(), buffer, dataSize);
+ // If it is a hotseat item, move it accordingly.
+ if (favorite.container == Favorites.CONTAINER_HOTSEAT) {
+ favorite.screen += mHotseatShift;
+ }
+
ContentValues values = new ContentValues();
values.put(Favorites._ID, favorite.id);
values.put(Favorites.SCREEN, favorite.screen);
@@ -969,6 +986,16 @@
widget.icon.data = Utilities.flattenBitmap(icon);
widget.icon.dpi = dpi;
}
+
+ // Calculate the spans corresponding to any one of the orientations as it should not change
+ // based on orientation.
+ int[] minSpans = CellLayout.rectToCell(
+ mIdp.portraitProfile, mContext, info.minResizeWidth, info.minResizeHeight, null);
+ widget.minSpanX = (info.resizeMode & LauncherAppWidgetProviderInfo.RESIZE_HORIZONTAL) != 0
+ ? minSpans[0] : -1;
+ widget.minSpanY = (info.resizeMode & LauncherAppWidgetProviderInfo.RESIZE_VERTICAL) != 0
+ ? minSpans[1] : -1;
+
return widget;
}
diff --git a/src/com/android/launcher3/LauncherModel.java b/src/com/android/launcher3/LauncherModel.java
index 7414a22..0b67310 100644
--- a/src/com/android/launcher3/LauncherModel.java
+++ b/src/com/android/launcher3/LauncherModel.java
@@ -1999,7 +1999,7 @@
"constructing info for partially restored package",
true);
info = getRestoredItemInfo(c, titleIndex, intent,
- promiseType, cursorIconInfo, context);
+ promiseType, itemType, cursorIconInfo, context);
intent = getRestoredItemIntent(c, context, intent);
} else {
// Don't restore items for other profiles.
@@ -2163,7 +2163,11 @@
appWidgetInfo = new LauncherAppWidgetInfo(appWidgetId,
provider.provider);
- int status = restoreStatus;
+ // The provider is available. So the widget is either
+ // available or not available. We do not need to track
+ // any future restore updates.
+ int status = restoreStatus &
+ ~LauncherAppWidgetInfo.FLAG_RESTORE_STARTED;
if (!wasProviderReady) {
// If provider was not previously ready, update the
// status and UI flag.
@@ -2209,6 +2213,7 @@
appWidgetInfo.cellY = c.getInt(cellYIndex);
appWidgetInfo.spanX = c.getInt(spanXIndex);
appWidgetInfo.spanY = c.getInt(spanYIndex);
+ appWidgetInfo.user = user;
if (container != LauncherSettings.Favorites.CONTAINER_DESKTOP &&
container != LauncherSettings.Favorites.CONTAINER_HOTSEAT) {
@@ -3154,7 +3159,9 @@
if (mUser.equals(widgetInfo.user)
&& widgetInfo.hasRestoreFlag(LauncherAppWidgetInfo.FLAG_PROVIDER_NOT_READY)
&& packageSet.contains(widgetInfo.providerName.getPackageName())) {
- widgetInfo.restoreStatus &= ~LauncherAppWidgetInfo.FLAG_PROVIDER_NOT_READY;
+ widgetInfo.restoreStatus &=
+ ~LauncherAppWidgetInfo.FLAG_PROVIDER_NOT_READY &
+ ~LauncherAppWidgetInfo.FLAG_RESTORE_STARTED;
widgets.add(widgetInfo);
updateItemInDatabase(context, widgetInfo);
}
@@ -3380,7 +3387,7 @@
* to a package that is not yet installed on the system.
*/
public ShortcutInfo getRestoredItemInfo(Cursor c, int titleIndex, Intent intent,
- int promiseType, CursorIconInfo iconInfo, Context context) {
+ int promiseType, int itemType, CursorIconInfo iconInfo, Context context) {
final ShortcutInfo info = new ShortcutInfo();
info.user = UserHandleCompat.myUserHandle();
@@ -3406,7 +3413,7 @@
}
info.contentDescription = mUserManager.getBadgedLabelForUser(info.title, info.user);
- info.itemType = LauncherSettings.Favorites.ITEM_TYPE_SHORTCUT;
+ info.itemType = itemType;
info.promisedIntent = intent;
info.status = promiseType;
return info;
diff --git a/src/com/android/launcher3/LauncherProvider.java b/src/com/android/launcher3/LauncherProvider.java
index ee72aea..cc5e18b 100644
--- a/src/com/android/launcher3/LauncherProvider.java
+++ b/src/com/android/launcher3/LauncherProvider.java
@@ -772,7 +772,7 @@
long id = c.getLong(idIndex);
updateStmt.bindLong(1, id);
- updateStmt.execute();
+ updateStmt.executeUpdateDelete();
}
db.setTransactionSuccessful();
} catch (SQLException ex) {
diff --git a/src/com/android/launcher3/LauncherStateTransitionAnimation.java b/src/com/android/launcher3/LauncherStateTransitionAnimation.java
index 0ea9d8b..d69b743 100644
--- a/src/com/android/launcher3/LauncherStateTransitionAnimation.java
+++ b/src/com/android/launcher3/LauncherStateTransitionAnimation.java
@@ -90,21 +90,14 @@
* Private callbacks made during transition setup.
*/
static abstract class PrivateTransitionCallbacks {
- void onRevealViewVisible(View revealView, View contentView, View allAppsButtonView) {}
float getMaterialRevealViewFinalAlpha(View revealView) {
return 0;
}
- float getMaterialRevealViewFinalXDrift(View revealView) {
- return 0;
- }
- float getMaterialRevealViewFinalYDrift(View revealView) {
- return 0;
- }
float getMaterialRevealViewStartFinalRadius() {
return 0;
}
AnimatorListenerAdapter getMaterialRevealViewAnimatorListener(View revealView,
- View allAppsButtonView) {
+ View buttonView) {
return null;
}
void onTransitionComplete() {}
@@ -135,30 +128,13 @@
public void startAnimationToAllApps(final boolean animated,
final boolean startSearchAfterTransition) {
final AllAppsContainerView toView = mLauncher.getAppsView();
+ final View buttonView = mLauncher.getAllAppsButton();
PrivateTransitionCallbacks cb = new PrivateTransitionCallbacks() {
- private int[] mAllAppsToPanelDelta;
-
- @Override
- public void onRevealViewVisible(View revealView, View contentView,
- View allAppsButtonView) {
- // Get the y delta between the center of the page and the center of the all apps
- // button
- mAllAppsToPanelDelta = Utilities.getCenterDeltaInScreenSpace(revealView,
- allAppsButtonView, null);
- }
@Override
public float getMaterialRevealViewFinalAlpha(View revealView) {
return 1f;
}
@Override
- public float getMaterialRevealViewFinalXDrift(View revealView) {
- return mAllAppsToPanelDelta[0];
- }
- @Override
- public float getMaterialRevealViewFinalYDrift(View revealView) {
- return mAllAppsToPanelDelta[1];
- }
- @Override
public float getMaterialRevealViewStartFinalRadius() {
int allAppsButtonSize = mLauncher.getDeviceProfile().allAppsButtonVisualSize;
return allAppsButtonSize / 2;
@@ -183,9 +159,9 @@
}
};
// Only animate the search bar if animating from spring loaded mode back to all apps
- startAnimationToOverlay(Workspace.State.NORMAL_HIDDEN, toView, toView.getContentView(),
- toView.getRevealView(), toView.getSearchBarView(), animated,
- true /* hideSearchBar */, cb);
+ startAnimationToOverlay(Workspace.State.NORMAL_HIDDEN, buttonView, toView,
+ toView.getContentView(), toView.getRevealView(), toView.getSearchBarView(),
+ animated, true /* hideSearchBar */, cb);
}
/**
@@ -193,22 +169,15 @@
*/
public void startAnimationToWidgets(final boolean animated) {
final WidgetsContainerView toView = mLauncher.getWidgetsView();
- final Resources res = mLauncher.getResources();
+ final View buttonView = mLauncher.getWidgetsButton();
+
PrivateTransitionCallbacks cb = new PrivateTransitionCallbacks() {
@Override
- public void onRevealViewVisible(View revealView, View contentView,
- View allAppsButtonView) {
- }
- @Override
public float getMaterialRevealViewFinalAlpha(View revealView) {
return 0.3f;
}
- @Override
- public float getMaterialRevealViewFinalYDrift(View revealView) {
- return revealView.getMeasuredHeight() / 2;
- }
};
- startAnimationToOverlay(Workspace.State.OVERVIEW_HIDDEN, toView,
+ startAnimationToOverlay(Workspace.State.OVERVIEW_HIDDEN, buttonView, toView,
toView.getContentView(), toView.getRevealView(), null, animated,
true /* hideSearchBar */, cb);
}
@@ -238,23 +207,22 @@
* Creates and starts a new animation to a particular overlay view.
*/
@SuppressLint("NewApi")
- private void startAnimationToOverlay(final Workspace.State toWorkspaceState, final View toView,
- final View contentView, final View revealView, final View overlaySearchBarView,
- final boolean animated, final boolean hideSearchBar,
- final PrivateTransitionCallbacks pCb) {
+ private void startAnimationToOverlay(final Workspace.State toWorkspaceState,
+ final View buttonView, final View toView, final View contentView, final View revealView,
+ final View overlaySearchBarView, final boolean animated, final boolean hideSearchBar,
+ final PrivateTransitionCallbacks pCb) {
final Resources res = mLauncher.getResources();
final boolean material = Utilities.isLmpOrAbove();
final int revealDuration = res.getInteger(R.integer.config_overlayRevealTime);
final int itemsAlphaStagger =
res.getInteger(R.integer.config_overlayItemsAlphaStagger);
- final View allAppsButtonView = mLauncher.getAllAppsButton();
final View fromView = mLauncher.getWorkspace();
final HashMap<View, Integer> layerViews = new HashMap<>();
// If for some reason our views aren't initialized, don't animate
- boolean initialized = allAppsButtonView != null;
+ boolean initialized = buttonView != null;
// Cancel the current animation
cancelAnimation();
@@ -275,16 +243,17 @@
revealView.setAlpha(0f);
revealView.setTranslationY(0f);
revealView.setTranslationX(0f);
- pCb.onRevealViewVisible(revealView, contentView, allAppsButtonView);
// Calculate the final animation values
final float revealViewToAlpha;
final float revealViewToXDrift;
final float revealViewToYDrift;
if (material) {
+ int[] buttonViewToPanelDelta = Utilities.getCenterDeltaInScreenSpace(revealView,
+ buttonView, null);
revealViewToAlpha = pCb.getMaterialRevealViewFinalAlpha(revealView);
- revealViewToYDrift = pCb.getMaterialRevealViewFinalYDrift(revealView);
- revealViewToXDrift = pCb.getMaterialRevealViewFinalXDrift(revealView);
+ revealViewToYDrift = buttonViewToPanelDelta[1];
+ revealViewToXDrift = buttonViewToPanelDelta[0];
} else {
revealViewToAlpha = 0f;
revealViewToYDrift = 2 * height / 3;
@@ -337,10 +306,9 @@
mStateAnimation.play(itemsAlpha);
if (material) {
- // Animate the all apps button
float startRadius = pCb.getMaterialRevealViewStartFinalRadius();
AnimatorListenerAdapter listener = pCb.getMaterialRevealViewAnimatorListener(
- revealView, allAppsButtonView);
+ revealView, buttonView);
Animator reveal = UiThreadCircularReveal.createCircularReveal(revealView, width / 2,
height / 2, startRadius, revealRadius);
reveal.setDuration(revealDuration);
@@ -453,22 +421,6 @@
int[] mAllAppsToPanelDelta;
@Override
- public void onRevealViewVisible(View revealView, View contentView,
- View allAppsButtonView) {
- // Get the y delta between the center of the page and the center of the all apps
- // button
- mAllAppsToPanelDelta = Utilities.getCenterDeltaInScreenSpace(revealView,
- allAppsButtonView, null);
- }
- @Override
- public float getMaterialRevealViewFinalXDrift(View revealView) {
- return mAllAppsToPanelDelta[0];
- }
- @Override
- public float getMaterialRevealViewFinalYDrift(View revealView) {
- return mAllAppsToPanelDelta[1];
- }
- @Override
float getMaterialRevealViewFinalAlpha(View revealView) {
// No alpha anim from all apps
return 1f;
@@ -499,9 +451,10 @@
}
};
// Only animate the search bar if animating to spring loaded mode from all apps
- startAnimationToWorkspaceFromOverlay(toWorkspaceState, toWorkspacePage, appsView,
- appsView.getContentView(), appsView.getRevealView(), appsView.getSearchBarView(),
- animated, onCompleteRunnable, cb);
+ startAnimationToWorkspaceFromOverlay(toWorkspaceState, toWorkspacePage,
+ mLauncher.getAllAppsButton(), appsView, appsView.getContentView(),
+ appsView.getRevealView(), appsView.getSearchBarView(), animated,
+ onCompleteRunnable, cb);
}
/**
@@ -510,23 +463,14 @@
private void startAnimationToWorkspaceFromWidgets(final Workspace.State toWorkspaceState,
final int toWorkspacePage, final boolean animated, final Runnable onCompleteRunnable) {
final WidgetsContainerView widgetsView = mLauncher.getWidgetsView();
- final Resources res = mLauncher.getResources();
PrivateTransitionCallbacks cb = new PrivateTransitionCallbacks() {
@Override
- public void onRevealViewVisible(View revealView, View contentView,
- View allAppsButtonView) {
- }
- @Override
- public float getMaterialRevealViewFinalYDrift(View revealView) {
- return revealView.getMeasuredHeight() / 2;
- }
- @Override
float getMaterialRevealViewFinalAlpha(View revealView) {
- return 0.4f;
+ return 0.3f;
}
@Override
public AnimatorListenerAdapter getMaterialRevealViewAnimatorListener(
- final View revealView, final View allAppsButtonView) {
+ final View revealView, final View widgetsButtonView) {
return new AnimatorListenerAdapter() {
public void onAnimationEnd(Animator animation) {
// Hide the reveal view
@@ -535,31 +479,31 @@
};
}
};
- startAnimationToWorkspaceFromOverlay(toWorkspaceState, toWorkspacePage, widgetsView,
- widgetsView.getContentView(), widgetsView.getRevealView(), null, animated,
- onCompleteRunnable, cb);
+ startAnimationToWorkspaceFromOverlay(toWorkspaceState, toWorkspacePage,
+ mLauncher.getWidgetsButton(), widgetsView, widgetsView.getContentView(),
+ widgetsView.getRevealView(), null, animated, onCompleteRunnable, cb);
}
/**
* Creates and starts a new animation to the workspace.
*/
private void startAnimationToWorkspaceFromOverlay(final Workspace.State toWorkspaceState,
- final int toWorkspacePage, final View fromView, final View contentView,
- final View revealView, final View overlaySearchBarView, final boolean animated,
- final Runnable onCompleteRunnable, final PrivateTransitionCallbacks pCb) {
+ final int toWorkspacePage, final View buttonView, final View fromView,
+ final View contentView, final View revealView, final View overlaySearchBarView,
+ final boolean animated, final Runnable onCompleteRunnable,
+ final PrivateTransitionCallbacks pCb) {
final Resources res = mLauncher.getResources();
final boolean material = Utilities.isLmpOrAbove();
final int revealDuration = res.getInteger(R.integer.config_overlayRevealTime);
final int itemsAlphaStagger =
res.getInteger(R.integer.config_overlayItemsAlphaStagger);
- final View allAppsButtonView = mLauncher.getAllAppsButton();
final View toView = mLauncher.getWorkspace();
final HashMap<View, Integer> layerViews = new HashMap<>();
// If for some reason our views aren't initialized, don't animate
- boolean initialized = allAppsButtonView != null;
+ boolean initialized = buttonView != null;
// Cancel the current animation
cancelAnimation();
@@ -589,14 +533,15 @@
revealView.setAlpha(1f);
revealView.setTranslationY(0);
layerViews.put(revealView, BUILD_AND_SET_LAYER);
- pCb.onRevealViewVisible(revealView, contentView, allAppsButtonView);
// Calculate the final animation values
final float revealViewToXDrift;
final float revealViewToYDrift;
if (material) {
- revealViewToYDrift = pCb.getMaterialRevealViewFinalYDrift(revealView);
- revealViewToXDrift = pCb.getMaterialRevealViewFinalXDrift(revealView);
+ int[] buttonViewToPanelDelta = Utilities.getCenterDeltaInScreenSpace(revealView,
+ buttonView, null);
+ revealViewToYDrift = buttonViewToPanelDelta[1];
+ revealViewToXDrift = buttonViewToPanelDelta[0];
} else {
revealViewToYDrift = 2 * height / 3;
revealViewToXDrift = 0;
@@ -666,7 +611,7 @@
// Animate the all apps button
float finalRadius = pCb.getMaterialRevealViewStartFinalRadius();
AnimatorListenerAdapter listener =
- pCb.getMaterialRevealViewAnimatorListener(revealView, allAppsButtonView);
+ pCb.getMaterialRevealViewAnimatorListener(revealView, buttonView);
Animator reveal = UiThreadCircularReveal.createCircularReveal(revealView, width / 2,
height / 2, revealRadius, finalRadius);
reveal.setInterpolator(new LogDecelerateInterpolator(100, 0));
diff --git a/src/com/android/launcher3/model/WidgetsModel.java b/src/com/android/launcher3/model/WidgetsModel.java
index 09a3242..185dfca 100644
--- a/src/com/android/launcher3/model/WidgetsModel.java
+++ b/src/com/android/launcher3/model/WidgetsModel.java
@@ -8,10 +8,10 @@
import com.android.launcher3.AppFilter;
import com.android.launcher3.IconCache;
-import com.android.launcher3.LauncherAppState;
import com.android.launcher3.LauncherAppWidgetProviderInfo;
import com.android.launcher3.Utilities;
import com.android.launcher3.compat.AlphabeticIndexCompat;
+import com.android.launcher3.compat.AppWidgetManagerCompat;
import com.android.launcher3.compat.UserHandleCompat;
import java.util.ArrayList;
@@ -38,6 +38,7 @@
private ArrayList<Object> mRawList;
+ private final AppWidgetManagerCompat mAppWidgetMgr;
private final Comparator mWidgetAndShortcutNameComparator;
private final Comparator mAppNameComparator;
private final IconCache mIconCache;
@@ -45,6 +46,7 @@
private AlphabeticIndexCompat mIndexer;
public WidgetsModel(Context context, IconCache iconCache, AppFilter appFilter) {
+ mAppWidgetMgr = AppWidgetManagerCompat.getInstance(context);
mWidgetAndShortcutNameComparator = new WidgetsAndShortcutNameComparator(context);
mAppNameComparator = (new AppNameComparator(context)).getAppInfoComparator();
mIconCache = iconCache;
@@ -53,6 +55,7 @@
}
private WidgetsModel(WidgetsModel model) {
+ mAppWidgetMgr = model.mAppWidgetMgr;
mPackageItemInfos = (ArrayList<PackageItemInfo>) model.mPackageItemInfos.clone();
mWidgetsList = (HashMap<PackageItemInfo, ArrayList<Object>>) model.mWidgetsList.clone();
mRawList = (ArrayList<Object>) model.mRawList.clone();
@@ -104,26 +107,30 @@
// add and update.
for (Object o: rawWidgetsShortcuts) {
String packageName = "";
+ UserHandleCompat userHandle = null;
ComponentName componentName = null;
if (o instanceof LauncherAppWidgetProviderInfo) {
LauncherAppWidgetProviderInfo widgetInfo = (LauncherAppWidgetProviderInfo) o;
componentName = widgetInfo.provider;
packageName = widgetInfo.provider.getPackageName();
+ userHandle = mAppWidgetMgr.getUser(widgetInfo);
} else if (o instanceof ResolveInfo) {
ResolveInfo resolveInfo = (ResolveInfo) o;
componentName = new ComponentName(resolveInfo.activityInfo.packageName,
resolveInfo.activityInfo.name);
packageName = resolveInfo.activityInfo.packageName;
+ userHandle = UserHandleCompat.myUserHandle();
}
- if (componentName == null) {
- Log.e(TAG, String.format("Widget cannot be set for class=%s",
- o.getClass().toString()));
+ if (componentName == null || userHandle == null) {
+ Log.e(TAG, String.format("Widget cannot be set for %s.", o.getClass().toString()));
continue;
}
if (mAppFilter != null && !mAppFilter.shouldShowApp(componentName)) {
- Log.d(TAG, String.format("%s is filtered and not added to the widget tray.",
+ if (DEBUG) {
+ Log.d(TAG, String.format("%s is filtered and not added to the widget tray.",
packageName));
+ }
continue;
}
@@ -135,7 +142,7 @@
widgetsShortcutsList = new ArrayList<Object>();
widgetsShortcutsList.add(o);
pInfo = new PackageItemInfo(packageName);
- mIconCache.getTitleAndIconForApp(packageName, UserHandleCompat.myUserHandle(),
+ mIconCache.getTitleAndIconForApp(packageName, userHandle,
true /* userLowResIcon */, pInfo);
pInfo.titleSectionName = mIndexer.computeSectionName(pInfo.title);
mWidgetsList.put(pInfo, widgetsShortcutsList);
diff --git a/src/com/android/launcher3/util/UiThreadCircularReveal.java b/src/com/android/launcher3/util/UiThreadCircularReveal.java
index c8e1df2..3ca3aee 100644
--- a/src/com/android/launcher3/util/UiThreadCircularReveal.java
+++ b/src/com/android/launcher3/util/UiThreadCircularReveal.java
@@ -46,10 +46,8 @@
public void onAnimationUpdate(ValueAnimator arg0) {
float progress = arg0.getAnimatedFraction();
outlineProvider.setProgress(progress);
- if (Utilities.isLmpMR1OrAbove()) {
- revealView.invalidateOutline();
- } else {
- // On L, a bug requires calling a full view invalidate.
+ revealView.invalidateOutline();
+ if (!Utilities.isLmpMR1OrAbove()) {
revealView.invalidate();
}
}
diff --git a/src/com/android/launcher3/widget/PendingAddWidgetInfo.java b/src/com/android/launcher3/widget/PendingAddWidgetInfo.java
index 88a6ca4..758287a 100644
--- a/src/com/android/launcher3/widget/PendingAddWidgetInfo.java
+++ b/src/com/android/launcher3/widget/PendingAddWidgetInfo.java
@@ -23,6 +23,7 @@
import com.android.launcher3.LauncherAppWidgetProviderInfo;
import com.android.launcher3.LauncherSettings;
import com.android.launcher3.PendingAddItemInfo;
+import com.android.launcher3.compat.AppWidgetManagerCompat;
/**
* Meta data used for late binding of {@link LauncherAppWidgetProviderInfo}.
@@ -47,6 +48,7 @@
itemType = LauncherSettings.Favorites.ITEM_TYPE_APPWIDGET;
}
this.info = i;
+ user = AppWidgetManagerCompat.getInstance(launcher).getUser(i);
componentName = i.provider;
minWidth = i.minWidth;
minHeight = i.minHeight;
diff --git a/src/com/android/launcher3/widget/WidgetsListAdapter.java b/src/com/android/launcher3/widget/WidgetsListAdapter.java
index d07c955..d2ea252 100644
--- a/src/com/android/launcher3/widget/WidgetsListAdapter.java
+++ b/src/com/android/launcher3/widget/WidgetsListAdapter.java
@@ -163,13 +163,15 @@
ViewGroup container = (ViewGroup) mLayoutInflater.inflate(
R.layout.widgets_list_row_view, parent, false);
LinearLayout cellList = (LinearLayout) container.findViewById(R.id.widgets_cell_list);
- MarginLayoutParams lp = (MarginLayoutParams) cellList.getLayoutParams();
+
+ // if the end padding is 0, then container view (horizontal scroll view) doesn't respect
+ // the end of the linear layout width + the start padding and doesn't allow scrolling.
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
- lp.setMarginStart(mIndent);
+ cellList.setPaddingRelative(mIndent, 0, 1, 0);
} else {
- lp.leftMargin = mIndent;
+ cellList.setPadding(mIndent, 0, 1, 0);
}
- cellList.setLayoutParams(lp);
+
return new WidgetsRowViewHolder(container);
}