Adding support for badging instant app icons.

Change-Id: Idc43a1a83e0a93f70879730a0acefbc124f9c0e2
This commit is contained in:
Sunny Goyal
2017-08-28 15:29:18 -07:00
parent 1ad3c8f61e
commit f5523921c3
7 changed files with 130 additions and 21 deletions

View File

@@ -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>

View File

@@ -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>

View File

@@ -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);
@@ -478,12 +481,6 @@ public class IconCache {
}
private void applyCacheEntry(CacheEntry entry, ItemInfoWithIcon info) {
if (info instanceof ShortcutInfo
&& ((ShortcutInfo) info).hasStatusFlag(ShortcutInfo.FLAG_SUPPORTS_WEB_UI)
&& (entry.icon == null || isDefaultIcon(entry.icon, info.user))) {
// skip updating shortcut info if no icon and supports web ui
return;
}
info.title = Utilities.trim(entry.title);
info.contentDescription = entry.contentDescription;
info.iconBitmap = entry.icon == null ? getDefaultIcon(info.user) : entry.icon;
@@ -581,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;
@@ -589,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) {
@@ -625,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);

View File

@@ -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;
}

View File

@@ -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;
}

View File

@@ -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;
@@ -198,10 +199,11 @@ public class PackageUpdatedTask extends BaseModelUpdateTask {
if (cn != null && matcher.matches(si, cn)) {
AppInfo appInfo = addedOrUpdatedApps.get(cn);
if (mOp == OP_REMOVE
&& si.hasStatusFlag(ShortcutInfo.FLAG_SUPPORTS_WEB_UI)) {
if (si.hasStatusFlag(ShortcutInfo.FLAG_SUPPORTS_WEB_UI)) {
removedShortcuts.put(si.id, false);
continue;
if (mOp == OP_REMOVE) {
continue;
}
}
// For system apps, package manager send OP_UPDATE when an
@@ -220,22 +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;
}

View File

@@ -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();
}
}