diff --git a/proguard.flags b/proguard.flags index b8cade5726..cac8930d5d 100644 --- a/proguard.flags +++ b/proguard.flags @@ -102,6 +102,11 @@ public (...); } +# InstantAppResolver +-keep class com.android.quickstep.InstantAppResolverImpl { + public (...); +} + -keep interface com.android.launcher3.userevent.nano.LauncherLogProto.** { *; } diff --git a/quickstep/res/values/override.xml b/quickstep/res/values/override.xml index ba99d81c07..2bd9f8f6f3 100644 --- a/quickstep/res/values/override.xml +++ b/quickstep/res/values/override.xml @@ -16,5 +16,7 @@ com.android.launcher3.LauncherAppTransitionManagerImpl + + com.android.quickstep.InstantAppResolverImpl diff --git a/quickstep/src/com/android/quickstep/InstantAppResolverImpl.java b/quickstep/src/com/android/quickstep/InstantAppResolverImpl.java new file mode 100644 index 0000000000..12757c0f79 --- /dev/null +++ b/quickstep/src/com/android/quickstep/InstantAppResolverImpl.java @@ -0,0 +1,77 @@ +/* + * Copyright (C) 2018 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.quickstep; + +import android.content.ComponentName; +import android.content.Context; +import android.content.pm.ApplicationInfo; +import android.content.pm.InstantAppInfo; +import android.content.pm.PackageManager; +import android.util.Log; + +import com.android.launcher3.AppInfo; +import com.android.launcher3.util.InstantAppResolver; + +import java.util.ArrayList; +import java.util.List; + +/** + * Implementation of InstantAppResolver using platform APIs + */ +@SuppressWarnings("unused") +public class InstantAppResolverImpl extends InstantAppResolver { + + private static final String TAG = "InstantAppResolverImpl"; + public static final String COMPONENT_CLASS_MARKER = "@instantapp"; + + private final PackageManager mPM; + + public InstantAppResolverImpl(Context context) + throws NoSuchMethodException, ClassNotFoundException { + mPM = context.getPackageManager(); + } + + @Override + public boolean isInstantApp(ApplicationInfo info) { + return info.isInstantApp(); + } + + @Override + public boolean isInstantApp(AppInfo info) { + ComponentName cn = info.getTargetComponent(); + return cn != null && cn.getClassName().equals(COMPONENT_CLASS_MARKER); + } + + @Override + public List getInstantApps() { + try { + List result = new ArrayList<>(); + for (InstantAppInfo iai : mPM.getInstantApps()) { + ApplicationInfo info = iai.getApplicationInfo(); + if (info != null) { + result.add(info); + } + } + return result; + } catch (SecurityException se) { + Log.w(TAG, "getInstantApps failed. Launcher may not be the default home app.", se); + } catch (Exception e) { + Log.e(TAG, "Error calling API: getInstantApps", e); + } + return super.getInstantApps(); + } +} diff --git a/quickstep/src/com/android/quickstep/NormalizedIconLoader.java b/quickstep/src/com/android/quickstep/NormalizedIconLoader.java index 431fb30a12..3247312fee 100644 --- a/quickstep/src/com/android/quickstep/NormalizedIconLoader.java +++ b/quickstep/src/com/android/quickstep/NormalizedIconLoader.java @@ -29,6 +29,7 @@ import android.util.SparseArray; import com.android.launcher3.FastBitmapDrawable; import com.android.launcher3.graphics.BitmapInfo; +import com.android.launcher3.graphics.DrawableFactory; import com.android.launcher3.graphics.LauncherIcons; import com.android.systemui.shared.recents.model.IconLoader; import com.android.systemui.shared.recents.model.TaskKeyLruCache; @@ -40,11 +41,13 @@ import com.android.systemui.shared.recents.model.TaskKeyLruCache; public class NormalizedIconLoader extends IconLoader { private final SparseArray mDefaultIcons = new SparseArray<>(); + private final DrawableFactory mDrawableFactory; private LauncherIcons mLauncherIcons; public NormalizedIconLoader(Context context, TaskKeyLruCache iconCache, LruCache activityInfoCache) { super(context, iconCache, activityInfoCache); + mDrawableFactory = DrawableFactory.get(context); } @Override @@ -53,7 +56,7 @@ public class NormalizedIconLoader extends IconLoader { BitmapInfo info = mDefaultIcons.get(userId); if (info == null) { info = getBitmapInfo(Resources.getSystem() - .getDrawable(android.R.drawable.sym_def_app_icon), userId); + .getDrawable(android.R.drawable.sym_def_app_icon), userId, false); mDefaultIcons.put(userId, info); } @@ -63,22 +66,26 @@ public class NormalizedIconLoader extends IconLoader { @Override protected Drawable createBadgedDrawable(Drawable drawable, int userId) { - return new FastBitmapDrawable(getBitmapInfo(drawable, userId)); + return new FastBitmapDrawable(getBitmapInfo(drawable, userId, false)); } - private synchronized BitmapInfo getBitmapInfo(Drawable drawable, int userId) { + private synchronized BitmapInfo getBitmapInfo(Drawable drawable, int userId, + boolean isInstantApp) { if (mLauncherIcons == null) { mLauncherIcons = LauncherIcons.obtain(mContext); } // User version code O, so that the icon is always wrapped in an adaptive icon container. return mLauncherIcons.createBadgedIconBitmap(drawable, UserHandle.of(userId), - Build.VERSION_CODES.O); + Build.VERSION_CODES.O, isInstantApp); } @Override - protected Drawable getBadgedActivityIcon(ActivityInfo activityInfo, int userId) { - return createBadgedDrawable( - activityInfo.loadUnbadgedIcon(mContext.getPackageManager()), userId); + protected synchronized Drawable getBadgedActivityIcon(ActivityInfo activityInfo, int userId) { + BitmapInfo bitmapInfo = getBitmapInfo( + activityInfo.loadUnbadgedIcon(mContext.getPackageManager()), + userId, + activityInfo.applicationInfo.isInstantApp()); + return mDrawableFactory.newIcon(bitmapInfo, activityInfo); } } diff --git a/src/com/android/launcher3/FastBitmapDrawable.java b/src/com/android/launcher3/FastBitmapDrawable.java index 5354edf8fa..3873a819f4 100644 --- a/src/com/android/launcher3/FastBitmapDrawable.java +++ b/src/com/android/launcher3/FastBitmapDrawable.java @@ -58,7 +58,7 @@ public class FastBitmapDrawable extends Drawable { private static final ColorMatrix sTempFilterMatrix = new ColorMatrix(); protected final Paint mPaint = new Paint(Paint.FILTER_BITMAP_FLAG | Paint.ANTI_ALIAS_FLAG); - private final Bitmap mBitmap; + protected Bitmap mBitmap; protected final int mIconColor; private boolean mIsPressed; @@ -324,10 +324,9 @@ public class FastBitmapDrawable extends Drawable { return new MyConstantState(mBitmap, mIconColor); } - private static class MyConstantState extends ConstantState { - private final Bitmap mBitmap; - private final int mIconColor; - + protected static class MyConstantState extends ConstantState { + protected final Bitmap mBitmap; + protected final int mIconColor; public MyConstantState(Bitmap bitmap, int color) { mBitmap = bitmap; diff --git a/src/com/android/launcher3/IconCache.java b/src/com/android/launcher3/IconCache.java index f4ae62a173..ab730741f7 100644 --- a/src/com/android/launcher3/IconCache.java +++ b/src/com/android/launcher3/IconCache.java @@ -641,11 +641,8 @@ public class IconCache { // Load the full res icon for the application, but if useLowResIcon is set, then // only keep the low resolution icon instead of the larger full-sized icon BitmapInfo iconInfo = li.createBadgedIconBitmap( - appInfo.loadIcon(mPackageManager), user, appInfo.targetSdkVersion); - if (mInstantAppResolver.isInstantApp(appInfo)) { - li.badgeWithDrawable(iconInfo.icon, - mContext.getDrawable(R.drawable.ic_instant_app_badge)); - } + appInfo.loadIcon(mPackageManager), user, appInfo.targetSdkVersion, + mInstantAppResolver.isInstantApp(appInfo)); li.recycle(); Bitmap lowResIcon = generateLowResIcon(iconInfo.icon); diff --git a/src/com/android/launcher3/graphics/DrawableFactory.java b/src/com/android/launcher3/graphics/DrawableFactory.java index 3393469223..34a4e2d771 100644 --- a/src/com/android/launcher3/graphics/DrawableFactory.java +++ b/src/com/android/launcher3/graphics/DrawableFactory.java @@ -17,6 +17,7 @@ package com.android.launcher3.graphics; import android.content.Context; +import android.content.pm.ActivityInfo; import android.content.res.Resources; import android.graphics.Bitmap; import android.graphics.Canvas; @@ -70,6 +71,10 @@ public class DrawableFactory { return drawable; } + public FastBitmapDrawable newIcon(BitmapInfo info, ActivityInfo target) { + return new FastBitmapDrawable(info); + } + /** * Returns a FastBitmapDrawable with the icon. */ @@ -80,7 +85,6 @@ public class DrawableFactory { return new PreloadIconDrawable(info, mPreloadProgressPath, context); } - protected Path getPreloadProgressPath(Context context) { if (Utilities.ATLEAST_OREO) { try { diff --git a/src/com/android/launcher3/graphics/LauncherIcons.java b/src/com/android/launcher3/graphics/LauncherIcons.java index 4a9cdd9a0e..2e9ff239f3 100644 --- a/src/com/android/launcher3/graphics/LauncherIcons.java +++ b/src/com/android/launcher3/graphics/LauncherIcons.java @@ -104,6 +104,7 @@ public class LauncherIcons implements AutoCloseable { private IconNormalizer mNormalizer; private ShadowGenerator mShadowGenerator; + private Drawable mWrapperIcon; // sometimes we store linked lists of these things private LauncherIcons next; @@ -172,6 +173,16 @@ public class LauncherIcons implements AutoCloseable { * The bitmap is also visually normalized with other icons. */ public BitmapInfo createBadgedIconBitmap(Drawable icon, UserHandle user, int iconAppTargetSdk) { + return createBadgedIconBitmap(icon, user, iconAppTargetSdk, false); + } + + /** + * Returns a bitmap suitable for displaying as an icon at various launcher UIs like all apps + * view or workspace. The icon is badged for {@param user}. + * The bitmap is also visually normalized with other icons. + */ + public BitmapInfo createBadgedIconBitmap(Drawable icon, UserHandle user, int iconAppTargetSdk, + boolean isInstantApp) { float[] scale = new float[1]; icon = normalizeAndWrapToAdaptiveIcon(icon, iconAppTargetSdk, null, scale); Bitmap bitmap = createIconBitmap(icon, scale[0]); @@ -190,6 +201,9 @@ public class LauncherIcons implements AutoCloseable { } else { result = createIconBitmap(badged, 1f); } + } else if (isInstantApp) { + badgeWithDrawable(bitmap, mContext.getDrawable(R.drawable.ic_instant_app_badge)); + result = bitmap; } else { result = bitmap; } @@ -213,8 +227,11 @@ public class LauncherIcons implements AutoCloseable { float scale = 1f; if (Utilities.ATLEAST_OREO && iconAppTargetSdk >= Build.VERSION_CODES.O) { boolean[] outShape = new boolean[1]; - AdaptiveIconDrawable dr = (AdaptiveIconDrawable) - mContext.getDrawable(R.drawable.adaptive_icon_drawable_wrapper).mutate(); + if (mWrapperIcon == null) { + mWrapperIcon = mContext.getDrawable(R.drawable.adaptive_icon_drawable_wrapper) + .mutate(); + } + AdaptiveIconDrawable dr = (AdaptiveIconDrawable) mWrapperIcon; dr.setBounds(0, 0, 1, 1); scale = getNormalizer().getScale(icon, outIconBounds, dr.getIconMask(), outShape); if (Utilities.ATLEAST_OREO && !outShape[0] && !(icon instanceof AdaptiveIconDrawable)) {