summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--res/drawable/ic_instant_app_badge.xml43
-rw-r--r--res/layout/all_apps.xml5
-rw-r--r--res/values-v26/styles.xml6
-rw-r--r--res/values/attrs.xml1
-rw-r--r--res/values/config.xml5
-rw-r--r--res/values/styles.xml8
-rw-r--r--src/com/android/launcher3/AppInfo.java10
-rw-r--r--src/com/android/launcher3/BubbleTextView.java4
-rw-r--r--src/com/android/launcher3/ButtonDropTarget.java29
-rw-r--r--src/com/android/launcher3/DeleteDropTarget.java6
-rw-r--r--src/com/android/launcher3/DeviceProfile.java9
-rw-r--r--src/com/android/launcher3/DropTargetBar.java52
-rw-r--r--src/com/android/launcher3/IconCache.java11
-rw-r--r--src/com/android/launcher3/IconProvider.java3
-rw-r--r--src/com/android/launcher3/InfoDropTarget.java2
-rw-r--r--src/com/android/launcher3/ItemInfo.java12
-rw-r--r--src/com/android/launcher3/Launcher.java6
-rw-r--r--src/com/android/launcher3/LauncherCallbacks.java4
-rw-r--r--src/com/android/launcher3/ShortcutInfo.java24
-rw-r--r--src/com/android/launcher3/allapps/AllAppsContainerView.java5
-rw-r--r--src/com/android/launcher3/allapps/AllAppsGridAdapter.java17
-rw-r--r--src/com/android/launcher3/allapps/AllAppsTransitionController.java5
-rw-r--r--src/com/android/launcher3/allapps/AlphabeticalAppsList.java33
-rw-r--r--src/com/android/launcher3/allapps/SearchUiManager.java7
-rw-r--r--src/com/android/launcher3/allapps/search/AppsSearchContainerLayout.java13
-rw-r--r--src/com/android/launcher3/anim/SpringAnimationHandler.java27
-rw-r--r--src/com/android/launcher3/graphics/IconShapeOverride.java2
-rw-r--r--src/com/android/launcher3/graphics/LauncherIcons.java12
-rw-r--r--src/com/android/launcher3/model/CacheDataUpdatedTask.java2
-rw-r--r--src/com/android/launcher3/model/LoaderTask.java4
-rw-r--r--src/com/android/launcher3/model/PackageInstallStateChangedTask.java17
-rw-r--r--src/com/android/launcher3/model/PackageUpdatedTask.java35
-rw-r--r--src/com/android/launcher3/shortcuts/DeepShortcutManager.java2
-rw-r--r--src/com/android/launcher3/testing/LauncherExtension.java3
-rw-r--r--src/com/android/launcher3/util/ComponentKeyMapper.java50
-rw-r--r--src/com/android/launcher3/util/InstantAppResolver.java45
36 files changed, 427 insertions, 92 deletions
diff --git a/res/drawable/ic_instant_app_badge.xml b/res/drawable/ic_instant_app_badge.xml
new file mode 100644
index 000000000..cc532309c
--- /dev/null
+++ b/res/drawable/ic_instant_app_badge.xml
@@ -0,0 +1,43 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2017 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="@dimen/profile_badge_size"
+ android:height="@dimen/profile_badge_size"
+ android:viewportWidth="18"
+ android:viewportHeight="18">
+
+ <path
+ android:fillColor="@android:color/black"
+ android:fillType="evenOdd"
+ android:strokeWidth="1"
+ android:pathData="M 9 0 C 13.9705627485 0 18 4.02943725152 18 9 C 18 13.9705627485 13.9705627485 18 9 18 C 4.02943725152 18 0 13.9705627485 0 9 C 0 4.02943725152 4.02943725152 0 9 0 Z" />
+ <path
+ android:fillColor="@android:color/white"
+ android:fillType="evenOdd"
+ android:strokeWidth="1"
+ android:pathData="M 9 0 C 13.9705627485 0 18 4.02943725152 18 9 C 18 13.9705627485 13.9705627485 18 9 18 C 4.02943725152 18 0 13.9705627485 0 9 C 0 4.02943725152 4.02943725152 0 9 0 Z" />
+ <path
+ android:fillColor="@android:color/white"
+ android:fillType="evenOdd"
+ android:strokeWidth="1"
+ android:pathData="M 9 0 C 13.9705627485 0 18 4.02943725152 18 9 C 18 13.9705627485 13.9705627485 18 9 18 C 4.02943725152 18 0 13.9705627485 0 9 C 0 4.02943725152 4.02943725152 0 9 0 Z" />
+ <path
+ android:fillColor="@android:color/black"
+ android:fillAlpha="0.87"
+ android:fillType="evenOdd"
+ android:strokeWidth="1"
+ android:pathData="M 6 10.4123279 L 8.63934949 10.4123279 L 8.63934949 15.6 L 12.5577168 7.84517705 L 9.94547194 7.84517705 L 9.94547194 2 Z" />
+</vector> \ No newline at end of file
diff --git a/res/layout/all_apps.xml b/res/layout/all_apps.xml
index 6340619ab..39df2b193 100644
--- a/res/layout/all_apps.xml
+++ b/res/layout/all_apps.xml
@@ -68,11 +68,10 @@
</com.android.launcher3.allapps.AllAppsRecyclerViewContainerView>
<View
- style="@style/AllAppsNavBarProtection"
android:id="@+id/nav_bar_bg"
+ android:background="?attr/allAppsNavBarScrimColor"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_gravity="bottom"
- android:focusable="false"
- android:visibility="invisible" />
+ android:focusable="false" />
</com.android.launcher3.allapps.AllAppsContainerView> \ No newline at end of file
diff --git a/res/values-v26/styles.xml b/res/values-v26/styles.xml
index fd6fc4d50..b25f46a0c 100644
--- a/res/values-v26/styles.xml
+++ b/res/values-v26/styles.xml
@@ -26,10 +26,4 @@
<item name="android:colorPrimaryDark">#616161</item> <!-- Gray 700 -->
</style>
- <!-- From O and above, we show a dark nav bar in all-apps -->
- <style name="AllAppsNavBarProtection">
- <item name="android:alpha">0.6</item>
- <item name="android:background">?android:attr/colorPrimary</item>
- </style>
-
</resources>
diff --git a/res/values/attrs.xml b/res/values/attrs.xml
index 7b52dae5d..68b628fb7 100644
--- a/res/values/attrs.xml
+++ b/res/values/attrs.xml
@@ -20,6 +20,7 @@
<!-- Attributes used for launcher theme -->
<attr name="allAppsScrimColor" format="color" />
+ <attr name="allAppsNavBarScrimColor" format="color" />
<attr name="popupColorPrimary" format="color" />
<attr name="popupColorSecondary" format="color" />
<attr name="popupColorTertiary" format="color" />
diff --git a/res/values/config.xml b/res/values/config.xml
index b41172bb1..10b612ba2 100644
--- a/res/values/config.xml
+++ b/res/values/config.xml
@@ -1,7 +1,7 @@
<resources>
<!-- Dynamic Grid -->
<!-- Out of 100, the percent of space the overview bar should try and take vertically. -->
- <integer name="config_dynamic_grid_overview_icon_zone_percentage">20</integer>
+ <integer name="config_dynamic_grid_overview_icon_zone_percentage">22</integer>
<!-- Miscellaneous -->
<bool name="config_largeHeap">false</bool>
@@ -116,6 +116,9 @@
<!-- Name of a color extraction implementation class. -->
<string name="color_extraction_impl_class" translatable="false"></string>
+ <!-- Name of a subclass of com.android.launcher3.util.InstantAppResolver. Can be empty. -->
+ <string name="instant_app_resolver_class" translatable="false"></string>
+
<!-- Package name of the default wallpaper picker. -->
<string name="wallpaper_picker_package" translatable="false"></string>
diff --git a/res/values/styles.xml b/res/values/styles.xml
index 17bc7f9de..5d06705f8 100644
--- a/res/values/styles.xml
+++ b/res/values/styles.xml
@@ -30,6 +30,7 @@
<style name="BaseLauncherThemeWithCustomAttrs" parent="@style/BaseLauncherTheme">
<item name="allAppsScrimColor">#CCFFFFFF</item>
+ <item name="allAppsNavBarScrimColor">#66FFFFFF</item>
<item name="popupColorPrimary">#FFF</item>
<item name="popupColorSecondary">#F5F5F5</item> <!-- Gray 100 -->
<item name="popupColorTertiary">#E0E0E0</item> <!-- Gray 300 -->
@@ -62,6 +63,7 @@
<item name="android:colorControlHighlight">#A0FFFFFF</item>
<item name="android:colorPrimary">#FF333333</item>
<item name="allAppsScrimColor">#7A000000</item>
+ <item name="allAppsNavBarScrimColor">#80000000</item>
<item name="popupColorPrimary">?android:attr/colorPrimary</item>
<item name="popupColorSecondary">#424242</item> <!-- Gray 800 -->
<item name="popupColorTertiary">#757575</item> <!-- Gray 600 -->
@@ -103,12 +105,6 @@
<item name="android:includeFontPadding">false</item>
</style>
- <!-- Style for nav bar background in all-apps screen -->
- <style name="AllAppsNavBarProtection">
- <item name="android:alpha">?android:attr/spotShadowAlpha</item>
- <item name="android:background">@color/default_shadow_color_no_alpha</item>
- </style>
-
<!-- Base theme for BubbleTextView and sub classes -->
<style name="BaseIcon">
<item name="android:layout_width">match_parent</item>
diff --git a/src/com/android/launcher3/AppInfo.java b/src/com/android/launcher3/AppInfo.java
index 9ec26e26a..3da199635 100644
--- a/src/com/android/launcher3/AppInfo.java
+++ b/src/com/android/launcher3/AppInfo.java
@@ -95,10 +95,14 @@ public class AppInfo extends ItemInfoWithIcon {
}
public static Intent makeLaunchIntent(LauncherActivityInfo info) {
+ return makeLaunchIntent(info.getComponentName());
+ }
+
+ public static Intent makeLaunchIntent(ComponentName cn) {
return new Intent(Intent.ACTION_MAIN)
- .addCategory(Intent.CATEGORY_LAUNCHER)
- .setComponent(info.getComponentName())
- .setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED);
+ .addCategory(Intent.CATEGORY_LAUNCHER)
+ .setComponent(cn)
+ .setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED);
}
@Override
diff --git a/src/com/android/launcher3/BubbleTextView.java b/src/com/android/launcher3/BubbleTextView.java
index a63767c5d..ac842f92e 100644
--- a/src/com/android/launcher3/BubbleTextView.java
+++ b/src/com/android/launcher3/BubbleTextView.java
@@ -184,7 +184,7 @@ public class BubbleTextView extends TextView implements ItemInfoUpdateReceiver {
public void applyFromShortcutInfo(ShortcutInfo info, boolean promiseStateChanged) {
applyIconAndLabel(info.iconBitmap, info);
setTag(info);
- if (promiseStateChanged || info.isPromise()) {
+ if (promiseStateChanged || (info.hasPromiseIconUi())) {
applyPromiseState(promiseStateChanged);
}
@@ -481,7 +481,7 @@ public class BubbleTextView extends TextView implements ItemInfoUpdateReceiver {
public void applyPromiseState(boolean promiseStateChanged) {
if (getTag() instanceof ShortcutInfo) {
ShortcutInfo info = (ShortcutInfo) getTag();
- final boolean isPromise = info.isPromise();
+ final boolean isPromise = info.hasPromiseIconUi();
final int progressLevel = isPromise ?
((info.hasStatusFlag(ShortcutInfo.FLAG_INSTALL_SESSION_ACTIVE) ?
info.getInstallProgress() : 0)) : 100;
diff --git a/src/com/android/launcher3/ButtonDropTarget.java b/src/com/android/launcher3/ButtonDropTarget.java
index e4a322622..632e49059 100644
--- a/src/com/android/launcher3/ButtonDropTarget.java
+++ b/src/com/android/launcher3/ButtonDropTarget.java
@@ -29,6 +29,7 @@ import android.graphics.ColorMatrix;
import android.graphics.ColorMatrixColorFilter;
import android.graphics.Rect;
import android.graphics.drawable.Drawable;
+import android.text.TextUtils;
import android.util.AttributeSet;
import android.view.View;
import android.view.View.OnClickListener;
@@ -69,6 +70,7 @@ public abstract class ButtonDropTarget extends TextView
/** The paint applied to the drag view on hover */
protected int mHoverColor = 0;
+ protected CharSequence mText;
protected ColorStateList mOriginalTextColor;
protected Drawable mDrawable;
@@ -96,6 +98,7 @@ public abstract class ButtonDropTarget extends TextView
@Override
protected void onFinishInflate() {
super.onFinishInflate();
+ mText = getText();
mOriginalTextColor = getTextColors();
}
@@ -297,4 +300,30 @@ public abstract class ButtonDropTarget extends TextView
public int getTextColor() {
return getTextColors().getDefaultColor();
}
+
+ /**
+ * Returns True if any update was made.
+ */
+ public boolean updateText(boolean hide) {
+ if ((hide && getText().toString().isEmpty()) || (!hide && mText.equals(getText()))) {
+ return false;
+ }
+
+ setText(hide ? "" : mText);
+ return true;
+ }
+
+ public boolean isTextTruncated() {
+ int availableWidth = getMeasuredWidth();
+ if (mHideParentOnDisable) {
+ ViewGroup parent = (ViewGroup) getParent();
+ availableWidth = parent.getMeasuredWidth() - parent.getPaddingLeft()
+ - parent.getPaddingRight();
+ }
+ availableWidth -= (getPaddingLeft() + getPaddingRight() + mDrawable.getIntrinsicWidth()
+ + getCompoundDrawablePadding());
+ CharSequence displayedText = TextUtils.ellipsize(mText, getPaint(), availableWidth,
+ TextUtils.TruncateAt.END);
+ return !mText.equals(displayedText);
+ }
}
diff --git a/src/com/android/launcher3/DeleteDropTarget.java b/src/com/android/launcher3/DeleteDropTarget.java
index 975675a6f..4dcb64f01 100644
--- a/src/com/android/launcher3/DeleteDropTarget.java
+++ b/src/com/android/launcher3/DeleteDropTarget.java
@@ -65,9 +65,11 @@ public class DeleteDropTarget extends ButtonDropTarget {
* Set the drop target's text to either "Remove" or "Cancel" depending on the drag source.
*/
public void setTextBasedOnDragSource(DragSource dragSource) {
- if (!TextUtils.isEmpty(getText())) {
- setText(dragSource.supportsDeleteDropTarget() ? R.string.remove_drop_target_label
+ if (!TextUtils.isEmpty(mText)) {
+ mText = getResources().getString(dragSource.supportsDeleteDropTarget()
+ ? R.string.remove_drop_target_label
: android.R.string.cancel);
+ requestLayout();
}
}
diff --git a/src/com/android/launcher3/DeviceProfile.java b/src/com/android/launcher3/DeviceProfile.java
index 150bc5309..c8e4c4908 100644
--- a/src/com/android/launcher3/DeviceProfile.java
+++ b/src/com/android/launcher3/DeviceProfile.java
@@ -555,9 +555,9 @@ public class DeviceProfile {
int getOverviewModeButtonBarHeight() {
int zoneHeight = (int) (overviewModeIconZoneRatio * availableHeightPx);
- zoneHeight = Math.min(overviewModeMaxIconZoneHeightPx,
- Math.max(overviewModeMinIconZoneHeightPx, zoneHeight));
- return zoneHeight;
+ return Utilities.boundToRange(zoneHeight,
+ overviewModeMinIconZoneHeightPx,
+ overviewModeMaxIconZoneHeightPx);
}
public static int calculateCellWidth(int width, int countX) {
@@ -693,7 +693,8 @@ public class DeviceProfile {
lp = (FrameLayout.LayoutParams) overviewMode.getLayoutParams();
lp.width = Math.min(availableWidthPx, maxWidth);
- lp.height = getOverviewModeButtonBarHeight() + mInsets.bottom;
+ lp.height = getOverviewModeButtonBarHeight();
+ lp.bottomMargin = mInsets.bottom;
overviewMode.setLayoutParams(lp);
}
diff --git a/src/com/android/launcher3/DropTargetBar.java b/src/com/android/launcher3/DropTargetBar.java
index 0840b7015..29a1349d5 100644
--- a/src/com/android/launcher3/DropTargetBar.java
+++ b/src/com/android/launcher3/DropTargetBar.java
@@ -78,6 +78,58 @@ public class DropTargetBar extends LinearLayout implements DragController.DragLi
setupButtonDropTarget(this, dragController);
}
+ @Override
+ protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
+ super.onMeasure(widthMeasureSpec, heightMeasureSpec);
+
+ boolean hideText = hideTextHelper(false /* shouldUpdateText */, false /* no-op */);
+ if (hideTextHelper(true /* shouldUpdateText */, hideText)) {
+ // Text has changed, so we need to re-measure.
+ super.onMeasure(widthMeasureSpec, heightMeasureSpec);
+ }
+ }
+
+ /**
+ * Helper method that iterates through the children and returns whether any of the visible
+ * {@link ButtonDropTarget} has truncated text.
+ *
+ * @param shouldUpdateText If True, updates the text of all children.
+ * @param hideText If True and {@param shouldUpdateText} is True, clears the text of all
+ * children; otherwise it sets the original text value.
+ *
+ *
+ * @return If shouldUpdateText is True, returns whether any of the children updated their text.
+ * Else, returns whether any of the children have truncated their text.
+ */
+ private boolean hideTextHelper(boolean shouldUpdateText, boolean hideText) {
+ boolean result = false;
+ View visibleView;
+ ButtonDropTarget dropTarget;
+ for (int i = getChildCount() - 1; i >= 0; --i) {
+ if (getChildAt(i) instanceof ButtonDropTarget) {
+ visibleView = dropTarget = (ButtonDropTarget) getChildAt(i);
+ } else if (getChildAt(i) instanceof ViewGroup) {
+ // The Drop Target is wrapped in a FrameLayout.
+ visibleView = getChildAt(i);
+ dropTarget = (ButtonDropTarget) ((ViewGroup) visibleView).getChildAt(0);
+ } else {
+ // Ignore other views.
+ continue;
+ }
+
+ if (visibleView.getVisibility() == View.VISIBLE) {
+ if (shouldUpdateText) {
+ result |= dropTarget.updateText(hideText);
+ } else if (dropTarget.isTextTruncated()) {
+ result = true;
+ break;
+ }
+ }
+ }
+
+ return result;
+ }
+
private void setupButtonDropTarget(View view, DragController dragController) {
if (view instanceof ButtonDropTarget) {
ButtonDropTarget bdt = (ButtonDropTarget) view;
diff --git a/src/com/android/launcher3/IconCache.java b/src/com/android/launcher3/IconCache.java
index 3bcd7afb4..6f86954dc 100644
--- a/src/com/android/launcher3/IconCache.java
+++ b/src/com/android/launcher3/IconCache.java
@@ -47,6 +47,7 @@ import com.android.launcher3.config.FeatureFlags;
import com.android.launcher3.graphics.LauncherIcons;
import com.android.launcher3.model.PackageItemInfo;
import com.android.launcher3.util.ComponentKey;
+import com.android.launcher3.util.InstantAppResolver;
import com.android.launcher3.util.Preconditions;
import com.android.launcher3.util.Provider;
import com.android.launcher3.util.SQLiteCacheHelper;
@@ -94,6 +95,7 @@ public class IconCache {
private final LauncherAppsCompat mLauncherApps;
private final HashMap<ComponentKey, CacheEntry> mCache =
new HashMap<>(INITIAL_ICON_CACHE_CAPACITY);
+ private final InstantAppResolver mInstantAppResolver;
private final int mIconDpi;
@Thunk final IconDB mIconDb;
@@ -106,6 +108,7 @@ public class IconCache {
mPackageManager = context.getPackageManager();
mUserManager = UserManagerCompat.getInstance(mContext);
mLauncherApps = LauncherAppsCompat.getInstance(mContext);
+ mInstantAppResolver = InstantAppResolver.newInstance(mContext);
mIconDpi = inv.fillResIconDpi;
mIconDb = new IconDB(context, inv.iconBitmapSize);
@@ -575,7 +578,6 @@ public class IconCache {
// 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;
@@ -583,6 +585,9 @@ public class IconCache {
if (icon != null) {
entry.icon = LauncherIcons.createIconBitmap(icon, mContext);
}
+ if (!TextUtils.isEmpty(title) && entry.icon != null) {
+ mCache.put(cacheKey, entry);
+ }
}
private static ComponentKey getPackageKey(String packageName, UserHandle user) {
@@ -619,6 +624,10 @@ public class IconCache {
// only keep the low resolution icon instead of the larger full-sized icon
Bitmap icon = LauncherIcons.createBadgedIconBitmap(
appInfo.loadIcon(mPackageManager), user, mContext, appInfo.targetSdkVersion);
+ if (mInstantAppResolver.isInstantApp(appInfo)) {
+ icon = LauncherIcons.badgeWithDrawable(icon,
+ mContext.getDrawable(R.drawable.ic_instant_app_badge), mContext);
+ }
Bitmap lowResIcon = generateLowResIcon(icon);
entry.title = appInfo.loadLabel(mPackageManager);
entry.contentDescription = mUserManager.getBadgedLabelForUser(entry.title, user);
diff --git a/src/com/android/launcher3/IconProvider.java b/src/com/android/launcher3/IconProvider.java
index 687251514..4dee2b57d 100644
--- a/src/com/android/launcher3/IconProvider.java
+++ b/src/com/android/launcher3/IconProvider.java
@@ -2,6 +2,7 @@ package com.android.launcher3;
import android.content.pm.LauncherActivityInfo;
import android.graphics.drawable.Drawable;
+import android.os.Build;
import java.util.Locale;
@@ -17,7 +18,7 @@ public class IconProvider {
}
public void updateSystemStateString() {
- mSystemState = Locale.getDefault().toString();
+ mSystemState = Locale.getDefault().toString() + "," + Build.VERSION.SDK_INT;
}
public String getIconSystemState(String packageName) {
diff --git a/src/com/android/launcher3/InfoDropTarget.java b/src/com/android/launcher3/InfoDropTarget.java
index f088d1176..f919dd052 100644
--- a/src/com/android/launcher3/InfoDropTarget.java
+++ b/src/com/android/launcher3/InfoDropTarget.java
@@ -75,7 +75,7 @@ public class InfoDropTarget extends UninstallDropTarget {
if (info instanceof AppInfo) {
componentName = ((AppInfo) info).componentName;
} else if (info instanceof ShortcutInfo) {
- componentName = ((ShortcutInfo) info).intent.getComponent();
+ componentName = info.getTargetComponent();
} else if (info instanceof PendingAddItemInfo) {
componentName = ((PendingAddItemInfo) info).componentName;
} else if (info instanceof LauncherAppWidgetInfo) {
diff --git a/src/com/android/launcher3/ItemInfo.java b/src/com/android/launcher3/ItemInfo.java
index c5be096a2..fa3253c67 100644
--- a/src/com/android/launcher3/ItemInfo.java
+++ b/src/com/android/launcher3/ItemInfo.java
@@ -138,17 +138,11 @@ public class ItemInfo {
public ComponentName getTargetComponent() {
Intent intent = getIntent();
- if (intent == null) {
+ if (intent != null) {
+ return intent.getComponent();
+ } else {
return null;
}
- ComponentName cn = intent.getComponent();
- if (itemType == LauncherSettings.Favorites.ITEM_TYPE_SHORTCUT && cn == null) {
- // Legacy shortcuts may not have a componentName but just a packageName. In that case
- // create a dummy componentName instead of adding additional check everywhere.
- String pkg = intent.getPackage();
- return pkg == null ? null : new ComponentName(pkg, IconCache.EMPTY_CLASS_NAME);
- }
- return cn;
}
public void writeToValues(ContentWriter writer) {
diff --git a/src/com/android/launcher3/Launcher.java b/src/com/android/launcher3/Launcher.java
index 8492a7985..614d08669 100644
--- a/src/com/android/launcher3/Launcher.java
+++ b/src/com/android/launcher3/Launcher.java
@@ -113,7 +113,6 @@ import com.android.launcher3.pageindicators.PageIndicator;
import com.android.launcher3.popup.PopupContainerWithArrow;
import com.android.launcher3.popup.PopupDataProvider;
import com.android.launcher3.shortcuts.DeepShortcutManager;
-import com.android.launcher3.shortcuts.ShortcutKey;
import com.android.launcher3.userevent.nano.LauncherLogProto;
import com.android.launcher3.userevent.nano.LauncherLogProto.Action;
import com.android.launcher3.userevent.nano.LauncherLogProto.ContainerType;
@@ -121,6 +120,7 @@ import com.android.launcher3.userevent.nano.LauncherLogProto.ControlType;
import com.android.launcher3.util.ActivityResultInfo;
import com.android.launcher3.util.RunnableWithId;
import com.android.launcher3.util.ComponentKey;
+import com.android.launcher3.util.ComponentKeyMapper;
import com.android.launcher3.util.ItemInfoMatcher;
import com.android.launcher3.util.MultiHashMap;
import com.android.launcher3.util.PackageManagerHelper;
@@ -2424,7 +2424,7 @@ public class Launcher extends BaseActivity
}
// Check for abandoned promise
- if ((v instanceof BubbleTextView) && shortcut.isPromise()) {
+ if ((v instanceof BubbleTextView) && shortcut.hasPromiseIconUi()) {
String packageName = shortcut.intent.getComponent() != null ?
shortcut.intent.getComponent().getPackageName() : shortcut.intent.getPackage();
if (!TextUtils.isEmpty(packageName)) {
@@ -3068,7 +3068,7 @@ public class Launcher extends BaseActivity
*/
public void tryAndUpdatePredictedApps() {
if (mLauncherCallbacks != null) {
- List<ComponentKey> apps = mLauncherCallbacks.getPredictedApps();
+ List<ComponentKeyMapper<AppInfo>> apps = mLauncherCallbacks.getPredictedApps();
if (apps != null) {
mAppsView.setPredictedApps(apps);
}
diff --git a/src/com/android/launcher3/LauncherCallbacks.java b/src/com/android/launcher3/LauncherCallbacks.java
index d66b14c7d..c900e533b 100644
--- a/src/com/android/launcher3/LauncherCallbacks.java
+++ b/src/com/android/launcher3/LauncherCallbacks.java
@@ -21,7 +21,7 @@ import android.os.Bundle;
import android.view.Menu;
import android.view.View;
-import com.android.launcher3.util.ComponentKey;
+import com.android.launcher3.util.ComponentKeyMapper;
import java.io.FileDescriptor;
import java.io.PrintWriter;
@@ -91,7 +91,7 @@ public interface LauncherCallbacks {
*/
boolean shouldMoveToDefaultScreenOnHomeIntent();
boolean hasSettings();
- List<ComponentKey> getPredictedApps();
+ List<ComponentKeyMapper<AppInfo>> getPredictedApps();
int SEARCH_BAR_HEIGHT_NORMAL = 0, SEARCH_BAR_HEIGHT_TALL = 1;
/** Must return one of {@link #SEARCH_BAR_HEIGHT_NORMAL} or {@link #SEARCH_BAR_HEIGHT_TALL} */
int getSearchBarHeight();
diff --git a/src/com/android/launcher3/ShortcutInfo.java b/src/com/android/launcher3/ShortcutInfo.java
index f0d9367af..adf008bf4 100644
--- a/src/com/android/launcher3/ShortcutInfo.java
+++ b/src/com/android/launcher3/ShortcutInfo.java
@@ -17,6 +17,7 @@
package com.android.launcher3;
import android.annotation.TargetApi;
+import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.os.Build;
@@ -59,6 +60,11 @@ public class ShortcutInfo extends ItemInfoWithIcon {
public static final int FLAG_RESTORE_STARTED = 8; //0B1000;
/**
+ * Web UI supported.
+ */
+ public static final int FLAG_SUPPORTS_WEB_UI = 16; //0B10000;
+
+ /**
* Indicates if it represents a common type mentioned in {@link CommonAppTypeParser}.
* Upto 15 different types supported.
*/
@@ -188,6 +194,10 @@ public class ShortcutInfo extends ItemInfoWithIcon {
return hasStatusFlag(FLAG_RESTORED_ICON | FLAG_AUTOINSTALL_ICON);
}
+ public boolean hasPromiseIconUi() {
+ return isPromise() && !hasStatusFlag(FLAG_SUPPORTS_WEB_UI);
+ }
+
public int getInstallProgress() {
return mInstallProgress;
}
@@ -226,4 +236,18 @@ public class ShortcutInfo extends ItemInfoWithIcon {
public boolean isDisabled() {
return isDisabled != 0;
}
+
+ @Override
+ public ComponentName getTargetComponent() {
+ ComponentName cn = super.getTargetComponent();
+ if (cn == null && (itemType == LauncherSettings.Favorites.ITEM_TYPE_SHORTCUT
+ || hasStatusFlag(FLAG_SUPPORTS_WEB_UI))) {
+ // Legacy shortcuts and promise icons with web UI may not have a componentName but just
+ // a packageName. In that case create a dummy componentName instead of adding additional
+ // check everywhere.
+ String pkg = intent.getPackage();
+ return pkg == null ? null : new ComponentName(pkg, IconCache.EMPTY_CLASS_NAME);
+ }
+ return cn;
+ }
}
diff --git a/src/com/android/launcher3/allapps/AllAppsContainerView.java b/src/com/android/launcher3/allapps/AllAppsContainerView.java
index 97a87c16c..4eba5c6df 100644
--- a/src/com/android/launcher3/allapps/AllAppsContainerView.java
+++ b/src/com/android/launcher3/allapps/AllAppsContainerView.java
@@ -50,6 +50,7 @@ import com.android.launcher3.folder.Folder;
import com.android.launcher3.keyboard.FocusedItemDecorator;
import com.android.launcher3.userevent.nano.LauncherLogProto.Target;
import com.android.launcher3.util.ComponentKey;
+import com.android.launcher3.util.ComponentKeyMapper;
import com.android.launcher3.util.PackageUserKey;
import java.util.List;
@@ -116,7 +117,7 @@ public class AllAppsContainerView extends BaseContainerView implements DragSourc
/**
* Sets the current set of predicted apps.
*/
- public void setPredictedApps(List<ComponentKey> apps) {
+ public void setPredictedApps(List<ComponentKeyMapper<AppInfo>> apps) {
mApps.setPredictedApps(apps);
}
@@ -349,8 +350,6 @@ public class AllAppsContainerView extends BaseContainerView implements DragSourc
ViewGroup.LayoutParams navBarBgLp = navBarBg.getLayoutParams();
navBarBgLp.height = insets.bottom;
navBarBg.setLayoutParams(navBarBgLp);
- navBarBg.setVisibility(FeatureFlags.LAUNCHER3_GRADIENT_ALL_APPS
- ? View.INVISIBLE : View.VISIBLE);
}
}
diff --git a/src/com/android/launcher3/allapps/AllAppsGridAdapter.java b/src/com/android/launcher3/allapps/AllAppsGridAdapter.java
index ba4fbe061..1f60fcc73 100644
--- a/src/com/android/launcher3/allapps/AllAppsGridAdapter.java
+++ b/src/com/android/launcher3/allapps/AllAppsGridAdapter.java
@@ -448,9 +448,20 @@ public class AllAppsGridAdapter extends RecyclerView.Adapter<AllAppsGridAdapter.
row = Math.abs(numTotalRows - row);
}
- // We manipulate the stiffness, min, and max values based on the items distance to the
- // first row and the items distance to the center column to create the ^-shaped motion
- // effect.
+ calculateSpringValues(spring, row, col);
+ }
+
+ @Override
+ public void setDefaultValues(SpringAnimation spring) {
+ calculateSpringValues(spring, 0, mAppsPerRow / 2);
+ }
+
+ /**
+ * We manipulate the stiffness, min, and max values based on the items distance to the
+ * first row and the items distance to the center column to create the ^-shaped motion
+ * effect.
+ */
+ private void calculateSpringValues(SpringAnimation spring, int row, int col) {
float rowFactor = (1 + row) * 0.5f;
float colFactor = getColumnFactor(col, mAppsPerRow);
diff --git a/src/com/android/launcher3/allapps/AllAppsTransitionController.java b/src/com/android/launcher3/allapps/AllAppsTransitionController.java
index edfe0c15e..a1f2dd7e3 100644
--- a/src/com/android/launcher3/allapps/AllAppsTransitionController.java
+++ b/src/com/android/launcher3/allapps/AllAppsTransitionController.java
@@ -7,6 +7,7 @@ import android.animation.AnimatorSet;
import android.animation.ArgbEvaluator;
import android.animation.ObjectAnimator;
import android.graphics.Color;
+import android.support.animation.SpringAnimation;
import android.support.v4.graphics.ColorUtils;
import android.support.v4.view.animation.FastOutSlowInInterpolator;
import android.view.MotionEvent;
@@ -101,6 +102,7 @@ public class AllAppsTransitionController implements TouchController, SwipeDetect
private AnimatorSet mDiscoBounceAnimation;
private GradientView mGradientView;
+ private SpringAnimation mSearchSpring;
private SpringAnimationHandler mSpringAnimationHandler;
public AllAppsTransitionController(Launcher l) {
@@ -226,6 +228,7 @@ public class AllAppsTransitionController implements TouchController, SwipeDetect
}
mLauncher.showAppsView(true /* animated */, false /* updatePredictedApps */);
if (hasSpringAnimationHandler()) {
+ mSpringAnimationHandler.add(mSearchSpring, true /* setDefaultValues */);
// The icons are moving upwards, so we go to 0 from 1. (y-axis 1 is below 0.)
mSpringAnimationHandler.animateToFinalPosition(0 /* pos */, 1 /* startValue */);
}
@@ -499,6 +502,7 @@ public class AllAppsTransitionController implements TouchController, SwipeDetect
public void finishPullUp() {
mHotseat.setVisibility(View.INVISIBLE);
if (hasSpringAnimationHandler()) {
+ mSpringAnimationHandler.remove(mSearchSpring);
mSpringAnimationHandler.reset();
}
setProgress(0f);
@@ -544,6 +548,7 @@ public class AllAppsTransitionController implements TouchController, SwipeDetect
mWorkspace.getPageIndicator().getCaretDrawable(), mLauncher);
mAppsView.getSearchUiManager().addOnScrollRangeChangeListener(this);
mSpringAnimationHandler = mAppsView.getSpringAnimationHandler();
+ mSearchSpring = mAppsView.getSearchUiManager().getSpringForFling();
}
private boolean hasSpringAnimationHandler() {
diff --git a/src/com/android/launcher3/allapps/AlphabeticalAppsList.java b/src/com/android/launcher3/allapps/AlphabeticalAppsList.java
index 5e7a5cac5..6bbe3ea55 100644
--- a/src/com/android/launcher3/allapps/AlphabeticalAppsList.java
+++ b/src/com/android/launcher3/allapps/AlphabeticalAppsList.java
@@ -29,6 +29,7 @@ import com.android.launcher3.discovery.AppDiscoveryAppInfo;
import com.android.launcher3.discovery.AppDiscoveryItem;
import com.android.launcher3.discovery.AppDiscoveryUpdateState;
import com.android.launcher3.util.ComponentKey;
+import com.android.launcher3.util.ComponentKeyMapper;
import com.android.launcher3.util.LabelComparator;
import java.util.ArrayList;
@@ -173,7 +174,7 @@ public class AlphabeticalAppsList {
// The set of sections that we allow fast-scrolling to (includes non-merged sections)
private final List<FastScrollSectionInfo> mFastScrollerSections = new ArrayList<>();
// The set of predicted app component names
- private final List<ComponentKey> mPredictedAppComponents = new ArrayList<>();
+ private final List<ComponentKeyMapper<AppInfo>> mPredictedAppComponents = new ArrayList<>();
// The set of predicted apps resolved from the component names and the current set of apps
private final List<AppInfo> mPredictedApps = new ArrayList<>();
private final List<AppDiscoveryAppInfo> mDiscoveredApps = new ArrayList<>();
@@ -298,20 +299,20 @@ public class AlphabeticalAppsList {
updateAdapterItems();
}
- private List<AppInfo> processPredictedAppComponents(List<ComponentKey> components) {
+ private List<AppInfo> processPredictedAppComponents(List<ComponentKeyMapper<AppInfo>> components) {
if (mComponentToAppMap.isEmpty()) {
// Apps have not been bound yet.
return Collections.emptyList();
}
List<AppInfo> predictedApps = new ArrayList<>();
- for (ComponentKey ck : components) {
- AppInfo info = mComponentToAppMap.get(ck);
+ for (ComponentKeyMapper<AppInfo> mapper : components) {
+ AppInfo info = mapper.getItem(mComponentToAppMap);
if (info != null) {
predictedApps.add(info);
} else {
if (FeatureFlags.IS_DOGFOOD_BUILD) {
- Log.e(TAG, "Predicted app not found: " + ck);
+ Log.e(TAG, "Predicted app not found: " + mapper);
}
}
// Stop at the number of predicted apps
@@ -331,7 +332,7 @@ public class AlphabeticalAppsList {
* If the number of predicted apps is the same as the previous list of predicted apps,
* we can optimize by swapping them in place.
*/
- public void setPredictedApps(List<ComponentKey> apps) {
+ public void setPredictedApps(List<ComponentKeyMapper<AppInfo>> apps) {
mPredictedAppComponents.clear();
mPredictedAppComponents.addAll(apps);
@@ -472,14 +473,14 @@ public class AlphabeticalAppsList {
if (DEBUG_PREDICTIONS) {
if (mPredictedAppComponents.isEmpty() && !mApps.isEmpty()) {
- mPredictedAppComponents.add(new ComponentKey(mApps.get(0).componentName,
- Process.myUserHandle()));
- mPredictedAppComponents.add(new ComponentKey(mApps.get(0).componentName,
- Process.myUserHandle()));
- mPredictedAppComponents.add(new ComponentKey(mApps.get(0).componentName,
- Process.myUserHandle()));
- mPredictedAppComponents.add(new ComponentKey(mApps.get(0).componentName,
- Process.myUserHandle()));
+ mPredictedAppComponents.add(new ComponentKeyMapper<AppInfo>(new ComponentKey(mApps.get(0).componentName,
+ Process.myUserHandle())));
+ mPredictedAppComponents.add(new ComponentKeyMapper<AppInfo>(new ComponentKey(mApps.get(0).componentName,
+ Process.myUserHandle())));
+ mPredictedAppComponents.add(new ComponentKeyMapper<AppInfo>(new ComponentKey(mApps.get(0).componentName,
+ Process.myUserHandle())));
+ mPredictedAppComponents.add(new ComponentKeyMapper<AppInfo>(new ComponentKey(mApps.get(0).componentName,
+ Process.myUserHandle())));
}
}
@@ -644,8 +645,8 @@ public class AlphabeticalAppsList {
return result;
}
- public AppInfo findApp(ComponentKey key) {
- return mComponentToAppMap.get(key);
+ public AppInfo findApp(ComponentKeyMapper<AppInfo> mapper) {
+ return mapper.getItem(mComponentToAppMap);
}
/**
diff --git a/src/com/android/launcher3/allapps/SearchUiManager.java b/src/com/android/launcher3/allapps/SearchUiManager.java
index c0d78508f..34230e046 100644
--- a/src/com/android/launcher3/allapps/SearchUiManager.java
+++ b/src/com/android/launcher3/allapps/SearchUiManager.java
@@ -15,6 +15,8 @@
*/
package com.android.launcher3.allapps;
+import android.support.animation.SpringAnimation;
+import android.support.annotation.NonNull;
import android.view.KeyEvent;
/**
@@ -28,6 +30,11 @@ public interface SearchUiManager {
void initialize(AlphabeticalAppsList appsList, AllAppsRecyclerView recyclerView);
/**
+ * A {@link SpringAnimation} that will be used when the user flings.
+ */
+ @NonNull SpringAnimation getSpringForFling();
+
+ /**
* Notifies the search manager that the apps-list has changed and the search UI should be
* updated accordingly.
*/
diff --git a/src/com/android/launcher3/allapps/search/AppsSearchContainerLayout.java b/src/com/android/launcher3/allapps/search/AppsSearchContainerLayout.java
index d50455171..ddf6e5849 100644
--- a/src/com/android/launcher3/allapps/search/AppsSearchContainerLayout.java
+++ b/src/com/android/launcher3/allapps/search/AppsSearchContainerLayout.java
@@ -17,6 +17,9 @@ package com.android.launcher3.allapps.search;
import android.content.Context;
import android.graphics.Rect;
+import android.support.animation.FloatValueHolder;
+import android.support.animation.SpringAnimation;
+import android.support.animation.SpringForce;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.text.Selection;
@@ -62,6 +65,8 @@ public class AppsSearchContainerLayout extends FrameLayout
private View mDivider;
private HeaderElevationController mElevationController;
+ private SpringAnimation mSpring;
+
public AppsSearchContainerLayout(Context context) {
this(context, null);
}
@@ -81,6 +86,9 @@ public class AppsSearchContainerLayout extends FrameLayout
mSearchQueryBuilder = new SpannableStringBuilder();
Selection.setSelection(mSearchQueryBuilder, 0);
+
+ // Note: This spring does nothing.
+ mSpring = new SpringAnimation(new FloatValueHolder()).setSpring(new SpringForce(0));
}
@Override
@@ -127,6 +135,11 @@ public class AppsSearchContainerLayout extends FrameLayout
}
@Override
+ public @NonNull SpringAnimation getSpringForFling() {
+ return mSpring;
+ }
+
+ @Override
public void refreshSearchResult() {
mSearchBarController.refreshSearchResult();
}
diff --git a/src/com/android/launcher3/anim/SpringAnimationHandler.java b/src/com/android/launcher3/anim/SpringAnimationHandler.java
index 3e58adc3f..eec3a48ee 100644
--- a/src/com/android/launcher3/anim/SpringAnimationHandler.java
+++ b/src/com/android/launcher3/anim/SpringAnimationHandler.java
@@ -70,6 +70,20 @@ public class SpringAnimationHandler<T> {
}
/**
+ * Adds a spring to the list of springs handled by this class.
+ * @param spring The new spring to be added.
+ * @param setDefaultValues If True, sets the spring to the default
+ * {@link AnimationFactory} values.
+ */
+ public void add(SpringAnimation spring, boolean setDefaultValues) {
+ if (setDefaultValues) {
+ mAnimationFactory.setDefaultValues(spring);
+ }
+ spring.setStartVelocity(mCurrentVelocity);
+ mAnimations.add(spring);
+ }
+
+ /**
* Adds a new or recycled animation to the list of springs handled by this class.
*
* @param view The view the spring is attached to.
@@ -82,15 +96,17 @@ public class SpringAnimationHandler<T> {
view.setTag(R.id.spring_animation_tag, spring);
}
mAnimationFactory.update(spring, object);
- spring.setStartVelocity(mCurrentVelocity);
- mAnimations.add(spring);
+ add(spring, false /* setDefaultValues */);
}
/**
* Stops and removes the spring attached to {@param view}.
*/
public void remove(View view) {
- SpringAnimation animation = (SpringAnimation) view.getTag(R.id.spring_animation_tag);
+ remove((SpringAnimation) view.getTag(R.id.spring_animation_tag));
+ }
+
+ public void remove(SpringAnimation animation) {
if (animation.canSkipToEnd()) {
animation.skipToEnd();
}
@@ -226,6 +242,11 @@ public class SpringAnimationHandler<T> {
* Updates the value of {@param spring} based on {@param object}.
*/
void update(SpringAnimation spring, T object);
+
+ /**
+ * Sets the factory default values for the given {@param spring}.
+ */
+ void setDefaultValues(SpringAnimation spring);
}
/**
diff --git a/src/com/android/launcher3/graphics/IconShapeOverride.java b/src/com/android/launcher3/graphics/IconShapeOverride.java
index e2d1d50e4..654fa98bc 100644
--- a/src/com/android/launcher3/graphics/IconShapeOverride.java
+++ b/src/com/android/launcher3/graphics/IconShapeOverride.java
@@ -130,7 +130,7 @@ public class IconShapeOverride {
private final int mOverrideId;
private final String mOverrideValue;
- @SuppressWarnings("deprecated")
+ @SuppressWarnings("deprecation")
public ResourcesOverride(Resources parent, int overrideId, String overrideValue) {
super(parent.getAssets(), parent.getDisplayMetrics(), parent.getConfiguration());
mOverrideId = overrideId;
diff --git a/src/com/android/launcher3/graphics/LauncherIcons.java b/src/com/android/launcher3/graphics/LauncherIcons.java
index d95567492..7c80c3098 100644
--- a/src/com/android/launcher3/graphics/LauncherIcons.java
+++ b/src/com/android/launcher3/graphics/LauncherIcons.java
@@ -38,6 +38,7 @@ import android.os.UserHandle;
import android.support.annotation.Nullable;
import com.android.launcher3.AppInfo;
+import com.android.launcher3.FastBitmapDrawable;
import com.android.launcher3.IconCache;
import com.android.launcher3.LauncherAppState;
import com.android.launcher3.R;
@@ -192,13 +193,16 @@ public class LauncherIcons {
* Adds the {@param badge} on top of {@param srcTgt} using the badge dimensions.
*/
public static Bitmap badgeWithBitmap(Bitmap srcTgt, Bitmap badge, Context context) {
+ return badgeWithDrawable(srcTgt, new FastBitmapDrawable(badge), context);
+ }
+
+ public static Bitmap badgeWithDrawable(Bitmap srcTgt, Drawable badge, Context context) {
int badgeSize = context.getResources().getDimensionPixelSize(R.dimen.profile_badge_size);
synchronized (sCanvas) {
sCanvas.setBitmap(srcTgt);
- sCanvas.drawBitmap(badge, new Rect(0, 0, badge.getWidth(), badge.getHeight()),
- new Rect(srcTgt.getWidth() - badgeSize,
- srcTgt.getHeight() - badgeSize, srcTgt.getWidth(), srcTgt.getHeight()),
- new Paint(Paint.FILTER_BITMAP_FLAG));
+ int iconSize = srcTgt.getWidth();
+ badge.setBounds(iconSize - badgeSize, iconSize - badgeSize, iconSize, iconSize);
+ badge.draw(sCanvas);
sCanvas.setBitmap(null);
}
return srcTgt;
diff --git a/src/com/android/launcher3/model/CacheDataUpdatedTask.java b/src/com/android/launcher3/model/CacheDataUpdatedTask.java
index 7a27741c3..0139bd902 100644
--- a/src/com/android/launcher3/model/CacheDataUpdatedTask.java
+++ b/src/com/android/launcher3/model/CacheDataUpdatedTask.java
@@ -88,7 +88,7 @@ public class CacheDataUpdatedTask extends BaseModelUpdateTask {
case OP_CACHE_UPDATE:
return true;
case OP_SESSION_UPDATE:
- return si.isPromise();
+ return si.hasPromiseIconUi();
default:
return false;
}
diff --git a/src/com/android/launcher3/model/LoaderTask.java b/src/com/android/launcher3/model/LoaderTask.java
index c56325ad5..4756edcc0 100644
--- a/src/com/android/launcher3/model/LoaderTask.java
+++ b/src/com/android/launcher3/model/LoaderTask.java
@@ -431,6 +431,10 @@ public class LoaderTask implements Runnable {
}
}
+ if ((c.restoreFlag & ShortcutInfo.FLAG_SUPPORTS_WEB_UI) != 0) {
+ validTarget = false;
+ }
+
if (validTarget) {
// The shortcut points to a valid target (either no target
// or something which is ready to be used)
diff --git a/src/com/android/launcher3/model/PackageInstallStateChangedTask.java b/src/com/android/launcher3/model/PackageInstallStateChangedTask.java
index 1e0af6881..32dfe2537 100644
--- a/src/com/android/launcher3/model/PackageInstallStateChangedTask.java
+++ b/src/com/android/launcher3/model/PackageInstallStateChangedTask.java
@@ -16,6 +16,9 @@
package com.android.launcher3.model;
import android.content.ComponentName;
+import android.content.pm.ApplicationInfo;
+import android.content.pm.PackageManager;
+import android.os.Process;
import com.android.launcher3.AllAppsList;
import com.android.launcher3.AppInfo;
@@ -28,6 +31,7 @@ import com.android.launcher3.PromiseAppInfo;
import com.android.launcher3.ShortcutInfo;
import com.android.launcher3.compat.PackageInstallerCompat;
import com.android.launcher3.compat.PackageInstallerCompat.PackageInstallInfo;
+import com.android.launcher3.util.InstantAppResolver;
import java.util.ArrayList;
import java.util.HashSet;
@@ -46,6 +50,17 @@ public class PackageInstallStateChangedTask extends BaseModelUpdateTask {
@Override
public void execute(LauncherAppState app, BgDataModel dataModel, AllAppsList apps) {
if (mInstallInfo.state == PackageInstallerCompat.STATUS_INSTALLED) {
+ try {
+ // For instant apps we do not get package-add. Use setting events to update
+ // any pinned icons.
+ ApplicationInfo ai = app.getContext()
+ .getPackageManager().getApplicationInfo(mInstallInfo.packageName, 0);
+ if (InstantAppResolver.newInstance(app.getContext()).isInstantApp(ai)) {
+ app.getModel().onPackageAdded(ai.packageName, Process.myUserHandle());
+ }
+ } catch (PackageManager.NameNotFoundException e) {
+ // Ignore
+ }
// Ignore install success events as they are handled by Package add events.
return;
}
@@ -94,7 +109,7 @@ public class PackageInstallStateChangedTask extends BaseModelUpdateTask {
if (info instanceof ShortcutInfo) {
ShortcutInfo si = (ShortcutInfo) info;
ComponentName cn = si.getTargetComponent();
- if (si.isPromise() && (cn != null)
+ if (si.hasPromiseIconUi() && (cn != null)
&& mInstallInfo.packageName.equals(cn.getPackageName())) {
si.setInstallProgress(mInstallInfo.progress);
if (mInstallInfo.state == PackageInstallerCompat.STATUS_FAILED) {
diff --git a/src/com/android/launcher3/model/PackageUpdatedTask.java b/src/com/android/launcher3/model/PackageUpdatedTask.java
index 6c78d5bfc..13962a259 100644
--- a/src/com/android/launcher3/model/PackageUpdatedTask.java
+++ b/src/com/android/launcher3/model/PackageUpdatedTask.java
@@ -23,6 +23,7 @@ import android.os.Process;
import android.os.UserHandle;
import android.util.ArrayMap;
import android.util.Log;
+
import com.android.launcher3.AllAppsList;
import com.android.launcher3.AppInfo;
import com.android.launcher3.IconCache;
@@ -32,7 +33,6 @@ import com.android.launcher3.LauncherAppState;
import com.android.launcher3.LauncherAppWidgetInfo;
import com.android.launcher3.LauncherModel.CallbackTask;
import com.android.launcher3.LauncherModel.Callbacks;
-import com.android.launcher3.LauncherSettings;
import com.android.launcher3.LauncherSettings.Favorites;
import com.android.launcher3.SessionCommitReceiver;
import com.android.launcher3.ShortcutInfo;
@@ -46,6 +46,7 @@ import com.android.launcher3.util.ItemInfoMatcher;
import com.android.launcher3.util.LongArrayMap;
import com.android.launcher3.util.PackageManagerHelper;
import com.android.launcher3.util.PackageUserKey;
+
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
@@ -104,6 +105,7 @@ public class PackageUpdatedTask extends BaseModelUpdateTask {
SessionCommitReceiver.queueAppIconAddition(context, packages[i], mUser);
}
}
+ flagOp = FlagOp.removeFlag(ShortcutInfo.FLAG_DISABLED_NOT_AVAILABLE);
break;
}
case OP_UPDATE:
@@ -170,12 +172,12 @@ public class PackageUpdatedTask extends BaseModelUpdateTask {
}
}
+ final LongArrayMap<Boolean> removedShortcuts = new LongArrayMap<>();
+
// Update shortcut infos
if (mOp == OP_ADD || flagOp != FlagOp.NO_OP) {
final ArrayList<ShortcutInfo> updatedShortcuts = new ArrayList<>();
- final LongArrayMap<Boolean> removedShortcuts = new LongArrayMap<>();
final ArrayList<LauncherAppWidgetInfo> widgets = new ArrayList<>();
-
synchronized (dataModel) {
for (ItemInfo info : dataModel.itemsIdMap) {
if (info instanceof ShortcutInfo && mUser.equals(info.user)) {
@@ -197,6 +199,13 @@ public class PackageUpdatedTask extends BaseModelUpdateTask {
if (cn != null && matcher.matches(si, cn)) {
AppInfo appInfo = addedOrUpdatedApps.get(cn);
+ if (si.hasStatusFlag(ShortcutInfo.FLAG_SUPPORTS_WEB_UI)) {
+ removedShortcuts.put(si.id, false);
+ if (mOp == OP_REMOVE) {
+ continue;
+ }
+ }
+
// For system apps, package manager send OP_UPDATE when an
// app is enabled.
if (si.isPromise() && (mOp == OP_ADD || mOp == OP_UPDATE)) {
@@ -213,23 +222,20 @@ public class PackageUpdatedTask extends BaseModelUpdateTask {
appInfo = addedOrUpdatedApps.get(cn);
}
- if ((intent == null) || (appInfo == null)) {
+ if (intent != null && appInfo != null) {
+ si.intent = intent;
+ si.status = ShortcutInfo.DEFAULT;
+ infoUpdated = true;
+ } else if (si.hasPromiseIconUi()) {
removedShortcuts.put(si.id, true);
continue;
}
- si.intent = intent;
}
}
-
- si.status = ShortcutInfo.DEFAULT;
- infoUpdated = true;
- if (si.itemType == Favorites.ITEM_TYPE_APPLICATION) {
- iconCache.getTitleAndIcon(si, si.usingLowResIcon);
- }
}
- if (appInfo != null && Intent.ACTION_MAIN.equals(si.intent.getAction())
- && si.itemType == LauncherSettings.Favorites.ITEM_TYPE_APPLICATION) {
+ if ((mOp == OP_ADD || mOp == OP_UPDATE) &&
+ si.itemType == Favorites.ITEM_TYPE_APPLICATION) {
iconCache.getTitleAndIcon(si, si.usingLowResIcon);
infoUpdated = true;
}
@@ -308,7 +314,8 @@ public class PackageUpdatedTask extends BaseModelUpdateTask {
if (!removedPackages.isEmpty() || !removedComponents.isEmpty()) {
ItemInfoMatcher removeMatch = ItemInfoMatcher.ofPackages(removedPackages, mUser)
- .or(ItemInfoMatcher.ofComponents(removedComponents, mUser));
+ .or(ItemInfoMatcher.ofComponents(removedComponents, mUser))
+ .and(ItemInfoMatcher.ofItemIds(removedShortcuts, true));
deleteAndBindComponentsRemoved(removeMatch);
// Remove any queued items from the install queue
diff --git a/src/com/android/launcher3/shortcuts/DeepShortcutManager.java b/src/com/android/launcher3/shortcuts/DeepShortcutManager.java
index 5ce78dc3a..f44f5c8d9 100644
--- a/src/com/android/launcher3/shortcuts/DeepShortcutManager.java
+++ b/src/com/android/launcher3/shortcuts/DeepShortcutManager.java
@@ -66,7 +66,7 @@ public class DeepShortcutManager {
public static boolean supportsShortcuts(ItemInfo info) {
boolean isItemPromise = info instanceof com.android.launcher3.ShortcutInfo
- && ((com.android.launcher3.ShortcutInfo) info).isPromise();
+ && ((com.android.launcher3.ShortcutInfo) info).hasPromiseIconUi();
return info.itemType == LauncherSettings.Favorites.ITEM_TYPE_APPLICATION
&& !info.isDisabled() && !isItemPromise;
}
diff --git a/src/com/android/launcher3/testing/LauncherExtension.java b/src/com/android/launcher3/testing/LauncherExtension.java
index 8d4351884..e5842fa0a 100644
--- a/src/com/android/launcher3/testing/LauncherExtension.java
+++ b/src/com/android/launcher3/testing/LauncherExtension.java
@@ -11,6 +11,7 @@ import com.android.launcher3.AppInfo;
import com.android.launcher3.Launcher;
import com.android.launcher3.LauncherCallbacks;
import com.android.launcher3.util.ComponentKey;
+import com.android.launcher3.util.ComponentKeyMapper;
import java.io.FileDescriptor;
import java.io.PrintWriter;
@@ -197,7 +198,7 @@ public class LauncherExtension extends Launcher {
}
@Override
- public List<ComponentKey> getPredictedApps() {
+ public List<ComponentKeyMapper<AppInfo>> getPredictedApps() {
// To debug app predictions, enable AlphabeticalAppsList#DEBUG_PREDICTIONS
return new ArrayList<>();
}
diff --git a/src/com/android/launcher3/util/ComponentKeyMapper.java b/src/com/android/launcher3/util/ComponentKeyMapper.java
new file mode 100644
index 000000000..916176ac4
--- /dev/null
+++ b/src/com/android/launcher3/util/ComponentKeyMapper.java
@@ -0,0 +1,50 @@
+package com.android.launcher3.util;
+
+/**
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import android.support.annotation.Nullable;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+
+public class ComponentKeyMapper<T> {
+
+ protected final ComponentKey mComponentKey;
+
+ public ComponentKeyMapper(ComponentKey key) {
+ this.mComponentKey = key;
+ }
+
+ public @Nullable T getItem(Map<ComponentKey, T> map) {
+ return map.get(mComponentKey);
+ }
+
+ public String getPackage() {
+ return mComponentKey.componentName.getPackageName();
+ }
+
+ public String getComponentClass() {
+ return mComponentKey.componentName.getClassName();
+ }
+
+ @Override
+ public String toString() {
+ return mComponentKey.toString();
+ }
+
+}
diff --git a/src/com/android/launcher3/util/InstantAppResolver.java b/src/com/android/launcher3/util/InstantAppResolver.java
new file mode 100644
index 000000000..e60d76808
--- /dev/null
+++ b/src/com/android/launcher3/util/InstantAppResolver.java
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.launcher3.util;
+
+import android.content.Context;
+import android.content.pm.ApplicationInfo;
+
+import com.android.launcher3.R;
+import com.android.launcher3.Utilities;
+
+import java.util.Collections;
+import java.util.List;
+
+/**
+ * A wrapper class to access instant app related APIs.
+ */
+public class InstantAppResolver {
+
+ public static InstantAppResolver newInstance(Context context) {
+ return Utilities.getOverrideObject(
+ InstantAppResolver.class, context, R.string.instant_app_resolver_class);
+ }
+
+ public boolean isInstantApp(ApplicationInfo info) {
+ return false;
+ }
+
+ public List<ApplicationInfo> getInstantApps() {
+ return Collections.emptyList();
+ }
+}