Merge "Split ApplicationInfo into ApplicationInfo which is used for AllAppsView and ShortcutInfo which is used for the workspace."

This commit is contained in:
Joe Onorato
2010-02-12 13:08:11 -08:00
committed by Android (Google) Code Review
25 changed files with 633 additions and 610 deletions
+2 -2
View File
@@ -23,8 +23,8 @@
launcher:cellWidth="@dimen/workspace_cell_width"
launcher:cellHeight="@dimen/workspace_cell_height"
launcher:longAxisStartPadding="@dimen/button_bar_height"
launcher:longAxisEndPadding="@dimen/button_bar_height"
launcher:longAxisStartPadding="65dip"
launcher:longAxisEndPadding="65dip"
launcher:shortAxisStartPadding="0dip"
launcher:shortAxisEndPadding="0dip"
launcher:shortAxisCells="4"
+1 -1
View File
@@ -23,7 +23,7 @@
launcher:cellWidth="@dimen/workspace_cell_width"
launcher:cellHeight="@dimen/workspace_cell_height"
launcher:longAxisStartPadding="0dip"
launcher:longAxisStartPadding="8dip"
launcher:longAxisEndPadding="@dimen/button_bar_height"
launcher:shortAxisStartPadding="0dip"
launcher:shortAxisEndPadding="0dip"
+11 -9
View File
@@ -44,10 +44,13 @@ class AllAppsList {
/** The list of apps that have been modified since the last notify() call. */
public ArrayList<ApplicationInfo> modified = new ArrayList<ApplicationInfo>();
private IconCache mIconCache;
/**
* Boring constructor.
*/
public AllAppsList() {
public AllAppsList(IconCache iconCache) {
mIconCache = iconCache;
}
/**
@@ -82,9 +85,8 @@ class AllAppsList {
final List<ResolveInfo> matches = findActivitiesForPackage(context, packageName);
if (matches.size() > 0) {
Utilities.BubbleText bubble = new Utilities.BubbleText(context);
for (ResolveInfo info : matches) {
ApplicationInfo item = AppInfoCache.cache(info, context, bubble);
ApplicationInfo item = new ApplicationInfo(info, mIconCache);
data.add(item);
added.add(item);
}
@@ -105,9 +107,9 @@ class AllAppsList {
}
}
// This is more aggressive than it needs to be.
AppInfoCache.flush();
mIconCache.flush();
}
/**
* Add and remove icons for this package which has been updated.
*/
@@ -122,7 +124,7 @@ class AllAppsList {
if (packageName.equals(component.getPackageName())) {
if (!findActivity(matches, component)) {
removed.add(applicationInfo);
AppInfoCache.remove(component);
mIconCache.remove(component);
data.remove(i);
}
}
@@ -130,7 +132,6 @@ class AllAppsList {
// Find enabled activities and add them to the adapter
// Also updates existing activities with new labels/icons
Utilities.BubbleText bubble = new Utilities.BubbleText(context);
int count = matches.size();
for (int i = 0; i < count; i++) {
final ResolveInfo info = matches.get(i);
@@ -138,11 +139,12 @@ class AllAppsList {
info.activityInfo.applicationInfo.packageName,
info.activityInfo.name);
if (applicationInfo == null) {
applicationInfo = AppInfoCache.cache(info, context, bubble);
applicationInfo = new ApplicationInfo(info, mIconCache);
data.add(applicationInfo);
added.add(applicationInfo);
} else {
AppInfoCache.update(info, applicationInfo, context, bubble);
mIconCache.remove(applicationInfo.componentName);
mIconCache.getTitleAndIcon(applicationInfo, info);
modified.add(applicationInfo);
}
}
-177
View File
@@ -1,177 +0,0 @@
/*
* Copyright (C) 2008 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.launcher2;
import android.content.ComponentName;
import android.content.ContentResolver;
import android.content.ContentValues;
import android.content.Intent;
import android.content.Context;
import android.content.pm.ActivityInfo;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.content.res.Resources;
import android.database.Cursor;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.drawable.Drawable;
import android.graphics.drawable.BitmapDrawable;
import android.net.Uri;
import android.util.Log;
import android.os.Process;
import java.lang.ref.WeakReference;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
/**
* Cache of application icons. Icons can be made from any thread.
*/
public class AppInfoCache {
private static final String TAG = "Launcher.AppInfoCache";
private static final int INITIAL_ICON_CACHE_CAPACITY = 50;
private static final HashMap<ComponentName, ApplicationInfo> sCache =
new HashMap<ComponentName, ApplicationInfo>(INITIAL_ICON_CACHE_CAPACITY);
/**
* no public constructor.
*/
private AppInfoCache() {
}
/**
* For the given ResolveInfo, return an ApplicationInfo and cache the result for later.
*/
public static ApplicationInfo cache(ResolveInfo info, Context context,
Utilities.BubbleText bubble) {
synchronized (sCache) {
ComponentName componentName = new ComponentName(
info.activityInfo.applicationInfo.packageName,
info.activityInfo.name);
ApplicationInfo application = sCache.get(componentName);
if (application == null) {
application = new ApplicationInfo();
application.container = ItemInfo.NO_ID;
updateTitleAndIcon(info, application, context, bubble);
application.setActivity(componentName,
Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED);
sCache.put(componentName, application);
}
return application;
}
}
/**
* Update the entry in the in the cache with its new metadata.
*/
public static void update(ResolveInfo info, ApplicationInfo applicationInfo, Context context,
Utilities.BubbleText bubble) {
synchronized (sCache) {
updateTitleAndIcon(info, applicationInfo, context, bubble);
ComponentName componentName = new ComponentName(
info.activityInfo.applicationInfo.packageName, info.activityInfo.name);
sCache.put(componentName, applicationInfo);
}
}
/**
* Remove any records for the supplied ComponentName.
*/
public static void remove(ComponentName componentName) {
synchronized (sCache) {
sCache.remove(componentName);
}
}
/**
* Empty out the cache.
*/
public static void flush() {
synchronized (sCache) {
sCache.clear();
}
}
/**
* Get the icon for the supplied ApplicationInfo. If that activity already
* exists in the cache, use that.
*/
public static Drawable getIconDrawable(PackageManager packageManager, ApplicationInfo info) {
final ResolveInfo resolveInfo = packageManager.resolveActivity(info.intent, 0);
if (resolveInfo == null) {
return null;
}
ComponentName componentName = new ComponentName(
resolveInfo.activityInfo.applicationInfo.packageName,
resolveInfo.activityInfo.name);
ApplicationInfo cached;
synchronized (sCache) {
cached = sCache.get(componentName);
if (cached != null) {
if (cached.icon == null) {
cached.icon = resolveInfo.activityInfo.loadIcon(packageManager);
}
return cached.icon;
} else {
return resolveInfo.activityInfo.loadIcon(packageManager);
}
}
}
/**
* Go through the cache and disconnect any of the callbacks in the drawables or we
* leak the previous Home screen on orientation change.
*/
public static void unbindDrawables() {
synchronized (sCache) {
for (ApplicationInfo appInfo: sCache.values()) {
if (appInfo.icon != null) {
appInfo.icon.setCallback(null);
}
}
}
}
/**
* Update the title and icon. Don't keep a reference to the context!
*/
private static void updateTitleAndIcon(ResolveInfo info, ApplicationInfo application,
Context context, Utilities.BubbleText bubble) {
final PackageManager packageManager = context.getPackageManager();
application.title = info.loadLabel(packageManager);
if (application.title == null) {
application.title = info.activityInfo.name;
}
application.iconBitmap = Utilities.createAllAppsBitmap(
info.activityInfo.loadIcon(packageManager), context);
application.titleBitmap = bubble.createTextBitmap(application.title.toString());
}
}
+25 -66
View File
@@ -18,7 +18,9 @@ package com.android.launcher2;
import android.content.ComponentName;
import android.content.ContentValues;
import android.content.Context;
import android.content.Intent;
import android.content.pm.ResolveInfo;
import android.graphics.Bitmap;
import android.graphics.drawable.Drawable;
import android.util.Log;
@@ -26,8 +28,7 @@ import android.util.Log;
import java.util.ArrayList;
/**
* Represents a launchable application. An application is made of a name (or title),
* an intent and an icon.
* Represents an app in AllAppsView.
*/
class ApplicationInfo extends ItemInfo {
@@ -46,49 +47,38 @@ class ApplicationInfo extends ItemInfo {
*/
Intent intent;
/**
* The application icon.
*/
Drawable icon;
/**
* A bitmap version of the application icon.
*/
Bitmap iconBitmap;
/**
* When set to true, indicates that the icon has been resized.
*/
boolean filtered;
ComponentName componentName;
/**
* Indicates whether the icon comes from an application's resource (if false)
* or from a custom Bitmap (if true.)
*/
boolean customIcon;
/**
* If isShortcut=true and customIcon=false, this contains a reference to the
* shortcut icon as an application's resource.
*/
Intent.ShortcutIconResource iconResource;
ApplicationInfo() {
itemType = LauncherSettings.BaseLauncherColumns.ITEM_TYPE_SHORTCUT;
}
/**
* Must not hold the Context.
*/
public ApplicationInfo(ResolveInfo info, IconCache iconCache) {
this.componentName = new ComponentName(
info.activityInfo.applicationInfo.packageName,
info.activityInfo.name);
this.container = ItemInfo.NO_ID;
this.setActivity(componentName,
Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED);
iconCache.getTitleAndIcon(this, info);
}
public ApplicationInfo(ApplicationInfo info) {
super(info);
componentName = info.componentName;
title = info.title.toString();
intent = new Intent(info.intent);
if (info.iconResource != null) {
iconResource = new Intent.ShortcutIconResource();
iconResource.packageName = info.iconResource.packageName;
iconResource.resourceName = info.iconResource.resourceName;
}
icon = info.icon;
filtered = info.filtered;
customIcon = info.customIcon;
}
/**
@@ -106,52 +96,21 @@ class ApplicationInfo extends ItemInfo {
itemType = LauncherSettings.BaseLauncherColumns.ITEM_TYPE_APPLICATION;
}
@Override
void onAddToDatabase(ContentValues values) {
super.onAddToDatabase(values);
String titleStr = title != null ? title.toString() : null;
values.put(LauncherSettings.BaseLauncherColumns.TITLE, titleStr);
String uri = intent != null ? intent.toUri(0) : null;
values.put(LauncherSettings.BaseLauncherColumns.INTENT, uri);
if (customIcon) {
values.put(LauncherSettings.BaseLauncherColumns.ICON_TYPE,
LauncherSettings.BaseLauncherColumns.ICON_TYPE_BITMAP);
Bitmap bitmap = ((FastBitmapDrawable) icon).getBitmap();
writeBitmap(values, bitmap);
} else {
values.put(LauncherSettings.BaseLauncherColumns.ICON_TYPE,
LauncherSettings.BaseLauncherColumns.ICON_TYPE_RESOURCE);
if (iconResource != null) {
values.put(LauncherSettings.BaseLauncherColumns.ICON_PACKAGE,
iconResource.packageName);
values.put(LauncherSettings.BaseLauncherColumns.ICON_RESOURCE,
iconResource.resourceName);
}
}
}
@Override
public String toString() {
return title.toString();
}
@Override
void unbind() {
super.unbind();
icon.setCallback(null);
}
public static void dumpApplicationInfoList(String tag, String label,
ArrayList<ApplicationInfo> list) {
Log.d(tag, label + " size=" + list.size());
for (ApplicationInfo info: list) {
Log.d(tag, " title=\"" + info.title + "\" titleBitmap=" + info.titleBitmap
+ " icon=" + info.icon + " iconBitmap=" + info.iconBitmap
+ " filtered=" + info.filtered + " customIcon=" + info.customIcon);
+ " iconBitmap=" + info.iconBitmap);
}
}
public ShortcutInfo makeShortcut() {
return new ShortcutInfo(this);
}
}
+2 -2
View File
@@ -101,9 +101,9 @@ public class DeleteZone extends ImageView implements DropTarget, DragController.
if (source instanceof UserFolder) {
final UserFolder userFolder = (UserFolder) source;
final UserFolderInfo userFolderInfo = (UserFolderInfo) userFolder.getInfo();
// item must be an ApplicationInfo otherwise it couldn't have been in the folder
// Item must be a ShortcutInfo otherwise it couldn't have been in the folder
// in the first place.
userFolderInfo.remove((ApplicationInfo)item);
userFolderInfo.remove((ShortcutInfo)item);
}
}
if (item instanceof UserFolderInfo) {
@@ -67,6 +67,10 @@ class FastBitmapDrawable extends Drawable {
return mBitmap.getHeight();
}
public void setBitmap(Bitmap b) {
mBitmap = b;
}
public Bitmap getBitmap() {
return mBitmap;
}
+5 -5
View File
@@ -46,7 +46,7 @@ public class Folder extends LinearLayout implements DragSource, OnItemLongClickL
/**
* Which item is being dragged
*/
protected ApplicationInfo mDragItem;
protected ShortcutInfo mDragItem;
private boolean mCloneInfo;
/**
@@ -74,7 +74,7 @@ public class Folder extends LinearLayout implements DragSource, OnItemLongClickL
}
public void onItemClick(AdapterView parent, View v, int position, long id) {
ApplicationInfo app = (ApplicationInfo) parent.getItemAtPosition(position);
ShortcutInfo app = (ShortcutInfo) parent.getItemAtPosition(position);
mLauncher.startActivitySafely(app.intent);
}
@@ -93,9 +93,9 @@ public class Folder extends LinearLayout implements DragSource, OnItemLongClickL
return false;
}
ApplicationInfo app = (ApplicationInfo) parent.getItemAtPosition(position);
ShortcutInfo app = (ShortcutInfo) parent.getItemAtPosition(position);
if (mCloneInfo) {
app = new ApplicationInfo(app);
app = new ShortcutInfo(app);
}
mDragController.startDrag(view, this, app, DragController.DRAG_ACTION_COPY);
@@ -118,7 +118,7 @@ public class Folder extends LinearLayout implements DragSource, OnItemLongClickL
/**
* Sets the adapter used to populate the content area. The adapter must only
* contains ApplicationInfo items.
* contains ShortcutInfo items.
*
* @param adapter The list of applications to display in the folder.
*/
+7 -3
View File
@@ -48,7 +48,6 @@ public class FolderIcon extends BubbleTextView implements DropTarget {
final Resources resources = launcher.getResources();
Drawable d = resources.getDrawable(R.drawable.ic_launcher_folder);
d = Utilities.createIconThumbnail(d, launcher);
icon.mCloseIcon = d;
icon.mOpenIcon = resources.getDrawable(R.drawable.ic_launcher_folder_open);
icon.setCompoundDrawablesWithIntrinsicBounds(null, d, null, null);
@@ -77,8 +76,13 @@ public class FolderIcon extends BubbleTextView implements DropTarget {
public void onDrop(DragSource source, int x, int y, int xOffset, int yOffset,
DragView dragView, Object dragInfo) {
final ApplicationInfo item = (ApplicationInfo) dragInfo;
// TODO: update open folder that is looking at this data
ShortcutInfo item;
if (dragInfo instanceof ApplicationInfo) {
// Came from all apps -- make a copy
item = ((ApplicationInfo)dragInfo).makeShortcut();
} else {
item = (ShortcutInfo)dragInfo;
}
mInfo.add(item);
LauncherModel.addOrMoveItemInDatabase(mLauncher, item, mInfo.id, 0, 0, 0);
}
+138
View File
@@ -0,0 +1,138 @@
/*
* Copyright (C) 2008 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.launcher2;
import android.content.ComponentName;
import android.content.ContentResolver;
import android.content.ContentValues;
import android.content.Intent;
import android.content.Context;
import android.content.pm.ActivityInfo;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.content.res.Resources;
import android.database.Cursor;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.drawable.Drawable;
import android.graphics.drawable.BitmapDrawable;
import android.net.Uri;
import android.util.Log;
import android.os.Process;
import java.lang.ref.WeakReference;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
/**
* Cache of application icons. Icons can be made from any thread.
*/
public class IconCache {
private static final String TAG = "Launcher.IconCache";
private static final int INITIAL_ICON_CACHE_CAPACITY = 50;
private static class CacheEntry {
public Bitmap icon;
public String title;
public Bitmap titleBitmap;
}
private LauncherApplication mContext;
private PackageManager mPackageManager;
private Utilities.BubbleText mBubble;
private final HashMap<ComponentName, CacheEntry> mCache =
new HashMap<ComponentName, CacheEntry>(INITIAL_ICON_CACHE_CAPACITY);
public IconCache(LauncherApplication context) {
mContext = context;
mPackageManager = context.getPackageManager();
mBubble = new Utilities.BubbleText(context);
}
/**
* Remove any records for the supplied ComponentName.
*/
public void remove(ComponentName componentName) {
synchronized (mCache) {
mCache.remove(componentName);
}
}
/**
* Empty out the cache.
*/
public void flush() {
synchronized (mCache) {
mCache.clear();
}
}
/**
* Fill in "application" with the icon and label for "info."
*/
public void getTitleAndIcon(ApplicationInfo application, ResolveInfo info) {
synchronized (mCache) {
CacheEntry entry = cacheLocked(application.componentName, info);
application.title = entry.title;
application.titleBitmap = entry.titleBitmap;
application.iconBitmap = entry.icon;
}
}
public Bitmap getIcon(Intent intent) {
final ResolveInfo resolveInfo = mPackageManager.resolveActivity(intent, 0);
ComponentName component = intent.getComponent();
if (resolveInfo == null || component == null) {
return null;
}
CacheEntry entry = cacheLocked(component, resolveInfo);
return entry.icon;
}
public Bitmap getIcon(ComponentName component, ResolveInfo resolveInfo) {
if (resolveInfo == null || component == null) {
return null;
}
CacheEntry entry = cacheLocked(component, resolveInfo);
return entry.icon;
}
private CacheEntry cacheLocked(ComponentName componentName, ResolveInfo info) {
CacheEntry entry = mCache.get(componentName);
if (entry == null) {
entry = new CacheEntry();
entry.title = info.loadLabel(mPackageManager).toString();
if (entry.title == null) {
entry.title = info.activityInfo.name;
}
entry.titleBitmap = mBubble.createTextBitmap(entry.title.toString());
entry.icon = Utilities.createIconBitmap(
info.activityInfo.loadIcon(mPackageManager), mContext);
mCache.put(componentName, entry);
}
return entry;
}
}
@@ -63,7 +63,8 @@ public class InstallShortcutReceiver extends BroadcastReceiver {
// different places)
boolean duplicate = data.getBooleanExtra(Launcher.EXTRA_SHORTCUT_DUPLICATE, true);
if (duplicate || !LauncherModel.shortcutExists(context, name, intent)) {
Launcher.addShortcut(context, data, cell, true);
((LauncherApplication)context.getApplicationContext()).getModel()
.addShortcut(context, data, cell, true);
Toast.makeText(context, context.getString(R.string.shortcut_installed, name),
Toast.LENGTH_SHORT).show();
} else {
+18 -13
View File
@@ -112,21 +112,26 @@ class ItemInfo {
}
}
static byte[] flattenBitmap(Bitmap bitmap) {
// Try go guesstimate how much space the icon will take when serialized
// to avoid unnecessary allocations/copies during the write.
int size = bitmap.getWidth() * bitmap.getHeight() * 4;
ByteArrayOutputStream out = new ByteArrayOutputStream(size);
try {
bitmap.compress(Bitmap.CompressFormat.PNG, 100, out);
out.flush();
out.close();
return out.toByteArray();
} catch (IOException e) {
Log.w("Favorite", "Could not write icon");
return null;
}
}
static void writeBitmap(ContentValues values, Bitmap bitmap) {
if (bitmap != null) {
// Try go guesstimate how much space the icon will take when serialized
// to avoid unnecessary allocations/copies during the write.
int size = bitmap.getWidth() * bitmap.getHeight() * 4;
ByteArrayOutputStream out = new ByteArrayOutputStream(size);
try {
bitmap.compress(Bitmap.CompressFormat.PNG, 100, out);
out.flush();
out.close();
values.put(LauncherSettings.Favorites.ICON, out.toByteArray());
} catch (IOException e) {
Log.w("Favorite", "Could not write icon");
}
byte[] data = flattenBitmap(bitmap);
values.put(LauncherSettings.Favorites.ICON, data);
}
}
+23 -106
View File
@@ -191,6 +191,7 @@ public final class Launcher extends Activity
private Bundle mSavedInstanceState;
private LauncherModel mModel;
private IconCache mIconCache;
private ArrayList<ItemInfo> mDesktopItems = new ArrayList<ItemInfo>();
private static HashMap<Long, FolderInfo> mFolders = new HashMap<Long, FolderInfo>();
@@ -202,7 +203,9 @@ public final class Launcher extends Activity
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mModel = ((LauncherApplication)getApplication()).setLauncher(this);
LauncherApplication app = ((LauncherApplication)getApplication());
mModel = app.setLauncher(this);
mIconCache = app.getIconCache();
mDragController = new DragController(this);
mInflater = getLayoutInflater();
@@ -271,7 +274,7 @@ public final class Launcher extends Activity
localeConfiguration.mnc = mnc;
writeConfiguration(this, localeConfiguration);
AppInfoCache.flush();
mIconCache.flush();
}
}
@@ -615,7 +618,7 @@ public final class Launcher extends Activity
*
* @return A View inflated from R.layout.application.
*/
View createShortcut(ApplicationInfo info) {
View createShortcut(ShortcutInfo info) {
return createShortcut(R.layout.application,
(ViewGroup) mWorkspace.getChildAt(mWorkspace.getCurrentScreen()), info);
}
@@ -629,18 +632,12 @@ public final class Launcher extends Activity
*
* @return A View inflated from layoutResId.
*/
View createShortcut(int layoutResId, ViewGroup parent, ApplicationInfo info) {
View createShortcut(int layoutResId, ViewGroup parent, ShortcutInfo info) {
TextView favorite = (TextView) mInflater.inflate(layoutResId, parent, false);
if (info.icon == null) {
info.icon = AppInfoCache.getIconDrawable(getPackageManager(), info);
}
if (!info.filtered) {
info.icon = Utilities.createIconThumbnail(info.icon, this);
info.filtered = true;
}
favorite.setCompoundDrawablesWithIntrinsicBounds(null, info.icon, null, null);
favorite.setCompoundDrawablesWithIntrinsicBounds(null,
new FastBitmapDrawable(info.getIcon(mIconCache)),
null, null);
favorite.setText(info.title);
favorite.setTag(info);
favorite.setOnClickListener(this);
@@ -658,39 +655,17 @@ public final class Launcher extends Activity
cellInfo.screen = mWorkspace.getCurrentScreen();
if (!findSingleSlot(cellInfo)) return;
final ApplicationInfo info = infoFromApplicationIntent(context, data);
final ShortcutInfo info = mModel.getShortcutInfo(context.getPackageManager(),
data, context);
if (info != null) {
mWorkspace.addApplicationShortcut(info, cellInfo, isWorkspaceLocked());
}
}
private static ApplicationInfo infoFromApplicationIntent(Context context, Intent data) {
ComponentName component = data.getComponent();
PackageManager packageManager = context.getPackageManager();
ActivityInfo activityInfo = null;
try {
activityInfo = packageManager.getActivityInfo(component, 0 /* no flags */);
} catch (NameNotFoundException e) {
Log.e(TAG, "Couldn't find ActivityInfo for selected application", e);
}
if (activityInfo != null) {
ApplicationInfo itemInfo = new ApplicationInfo();
itemInfo.title = activityInfo.loadLabel(packageManager);
if (itemInfo.title == null) {
itemInfo.title = activityInfo.name;
}
itemInfo.setActivity(component, Intent.FLAG_ACTIVITY_NEW_TASK |
info.setActivity(data.getComponent(), Intent.FLAG_ACTIVITY_NEW_TASK |
Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED);
itemInfo.icon = activityInfo.loadIcon(packageManager);
itemInfo.container = ItemInfo.NO_ID;
return itemInfo;
info.container = ItemInfo.NO_ID;
mWorkspace.addApplicationShortcut(info, cellInfo, isWorkspaceLocked());
} else {
Log.e(TAG, "Couldn't find ActivityInfo for selected application: " + data);
}
return null;
}
/**
@@ -703,7 +678,7 @@ public final class Launcher extends Activity
cellInfo.screen = mWorkspace.getCurrentScreen();
if (!findSingleSlot(cellInfo)) return;
final ApplicationInfo info = addShortcut(this, data, cellInfo, false);
final ShortcutInfo info = mModel.addShortcut(this, data, cellInfo, false);
if (!mRestoring) {
final View view = createShortcut(info);
@@ -770,61 +745,6 @@ public final class Launcher extends Activity
return mAppWidgetHost;
}
static ApplicationInfo addShortcut(Context context, Intent data,
CellLayout.CellInfo cellInfo, boolean notify) {
final ApplicationInfo info = infoFromShortcutIntent(context, data);
LauncherModel.addItemToDatabase(context, info, LauncherSettings.Favorites.CONTAINER_DESKTOP,
cellInfo.screen, cellInfo.cellX, cellInfo.cellY, notify);
return info;
}
private static ApplicationInfo infoFromShortcutIntent(Context context, Intent data) {
Intent intent = data.getParcelableExtra(Intent.EXTRA_SHORTCUT_INTENT);
String name = data.getStringExtra(Intent.EXTRA_SHORTCUT_NAME);
Parcelable bitmap = data.getParcelableExtra(Intent.EXTRA_SHORTCUT_ICON);
Drawable icon = null;
boolean filtered = false;
boolean customIcon = false;
ShortcutIconResource iconResource = null;
if (bitmap != null && bitmap instanceof Bitmap) {
icon = new FastBitmapDrawable(Utilities.createBitmapThumbnail((Bitmap) bitmap, context));
filtered = true;
customIcon = true;
} else {
Parcelable extra = data.getParcelableExtra(Intent.EXTRA_SHORTCUT_ICON_RESOURCE);
if (extra != null && extra instanceof ShortcutIconResource) {
try {
iconResource = (ShortcutIconResource) extra;
final PackageManager packageManager = context.getPackageManager();
Resources resources = packageManager.getResourcesForApplication(
iconResource.packageName);
final int id = resources.getIdentifier(iconResource.resourceName, null, null);
icon = resources.getDrawable(id);
} catch (Exception e) {
Log.w(TAG, "Could not load shortcut icon: " + extra);
}
}
}
if (icon == null) {
icon = context.getPackageManager().getDefaultActivityIcon();
}
final ApplicationInfo info = new ApplicationInfo();
info.icon = icon;
info.filtered = filtered;
info.title = name;
info.intent = intent;
info.customIcon = customIcon;
info.iconResource = iconResource;
return info;
}
void closeSystemDialogs() {
getWindow().closeAllPanels();
@@ -936,7 +856,6 @@ public final class Launcher extends Activity
mModel.stopLoader();
unbindDesktopItems();
AppInfoCache.unbindDrawables();
getContentResolver().unregisterContentObserver(mWidgetObserver);
@@ -1163,7 +1082,6 @@ public final class Launcher extends Activity
String name = data.getStringExtra(LiveFolders.EXTRA_LIVE_FOLDER_NAME);
Drawable icon = null;
boolean filtered = false;
Intent.ShortcutIconResource iconResource = null;
Parcelable extra = data.getParcelableExtra(LiveFolders.EXTRA_LIVE_FOLDER_ICON);
@@ -1185,8 +1103,7 @@ public final class Launcher extends Activity
}
final LiveFolderInfo info = new LiveFolderInfo();
info.icon = icon;
info.filtered = filtered;
info.icon = Utilities.createIconBitmap(icon, context);
info.title = name;
info.iconResource = iconResource;
info.uri = data.getData();
@@ -1338,9 +1255,9 @@ public final class Launcher extends Activity
*/
public void onClick(View v) {
Object tag = v.getTag();
if (tag instanceof ApplicationInfo) {
if (tag instanceof ShortcutInfo) {
// Open shortcut
final Intent intent = ((ApplicationInfo) tag).intent;
final Intent intent = ((ShortcutInfo)tag).intent;
int[] pos = new int[2];
v.getLocationOnScreen(pos);
intent.setSourceBounds(
@@ -2011,7 +1928,7 @@ public final class Launcher extends Activity
switch (item.itemType) {
case LauncherSettings.Favorites.ITEM_TYPE_APPLICATION:
case LauncherSettings.Favorites.ITEM_TYPE_SHORTCUT:
final View shortcut = createShortcut((ApplicationInfo) item);
final View shortcut = createShortcut((ShortcutInfo)item);
workspace.addInScreen(shortcut, item.screen, item.cellX, item.cellY, 1, 1,
false);
break;
@@ -25,11 +25,8 @@ import android.os.Handler;
import dalvik.system.VMRuntime;
public class LauncherApplication extends Application {
public final LauncherModel mModel;
public LauncherApplication() {
mModel = new LauncherModel(this);
}
public LauncherModel mModel;
public IconCache mIconCache;
@Override
public void onCreate() {
@@ -37,6 +34,9 @@ public class LauncherApplication extends Application {
super.onCreate();
mIconCache = new IconCache(this);
mModel = new LauncherModel(this, mIconCache);
// Register intent receivers
IntentFilter filter = new IntentFilter(Intent.ACTION_PACKAGE_ADDED);
filter.addAction(Intent.ACTION_PACKAGE_REMOVED);
@@ -79,4 +79,12 @@ public class LauncherApplication extends Application {
mModel.initialize(launcher);
return mModel;
}
IconCache getIconCache() {
return mIconCache;
}
LauncherModel getModel() {
return mModel;
}
}
+99 -34
View File
@@ -24,6 +24,7 @@ import android.content.ContentProviderClient;
import android.content.ContentResolver;
import android.content.ContentValues;
import android.content.Intent;
import android.content.Intent.ShortcutIconResource;
import android.content.Context;
import android.content.pm.ActivityInfo;
import android.content.pm.PackageManager;
@@ -34,6 +35,7 @@ import android.database.Cursor;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.net.Uri;
import android.os.Parcelable;
import android.os.RemoteException;
import android.util.Log;
import android.os.Process;
@@ -65,7 +67,10 @@ public class LauncherModel extends BroadcastReceiver {
private boolean mBeforeFirstLoad = true;
private WeakReference<Callbacks> mCallbacks;
private AllAppsList mAllAppsList = new AllAppsList();
private AllAppsList mAllAppsList;
private IconCache mIconCache;
private Bitmap mDefaultIcon;
public interface Callbacks {
public int getCurrentWorkspaceScreen();
@@ -80,8 +85,17 @@ public class LauncherModel extends BroadcastReceiver {
public void bindPackageRemoved(String packageName, ArrayList<ApplicationInfo> apps);
}
LauncherModel(LauncherApplication app) {
LauncherModel(LauncherApplication app, IconCache iconCache) {
mApp = app;
mAllAppsList = new AllAppsList(iconCache);
mIconCache = iconCache;
mDefaultIcon = Utilities.createIconBitmap(
app.getPackageManager().getDefaultActivityIcon(), app);
}
public Bitmap getDefaultIcon() {
return Bitmap.createBitmap(mDefaultIcon);
}
/**
@@ -323,7 +337,7 @@ public class LauncherModel extends BroadcastReceiver {
removed = mAllAppsList.removed;
mAllAppsList.removed = new ArrayList<ApplicationInfo>();
for (ApplicationInfo info: removed) {
AppInfoCache.remove(info.intent.getComponent());
mIconCache.remove(info.intent.getComponent());
}
}
if (mAllAppsList.modified.size() > 0) {
@@ -658,7 +672,7 @@ public class LauncherModel extends BroadcastReceiver {
final int displayModeIndex = c.getColumnIndexOrThrow(
LauncherSettings.Favorites.DISPLAY_MODE);
ApplicationInfo info;
ShortcutInfo info;
String intentDescription;
LauncherAppWidgetInfo appWidgetInfo;
int container;
@@ -680,15 +694,15 @@ public class LauncherModel extends BroadcastReceiver {
}
if (itemType == LauncherSettings.Favorites.ITEM_TYPE_APPLICATION) {
info = getApplicationInfo(manager, intent, context);
info = getShortcutInfo(manager, intent, context);
} else {
info = getApplicationInfoShortcut(c, context, iconTypeIndex,
info = getShortcutInfo(c, context, iconTypeIndex,
iconPackageIndex, iconResourceIndex, iconIndex);
}
if (info == null) {
info = new ApplicationInfo();
info.icon = manager.getDefaultActivityIcon();
info = new ShortcutInfo();
info.setIcon(getDefaultIcon());
}
if (info != null) {
@@ -973,9 +987,7 @@ public class LauncherModel extends BroadcastReceiver {
return;
}
final Context context = mContext;
final PackageManager packageManager = context.getPackageManager();
final PackageManager packageManager = mContext.getPackageManager();
final List<ResolveInfo> apps = packageManager.queryIntentActivities(mainIntent, 0);
synchronized (mLock) {
@@ -986,10 +998,9 @@ public class LauncherModel extends BroadcastReceiver {
long t = SystemClock.uptimeMillis();
int N = apps.size();
Utilities.BubbleText bubble = new Utilities.BubbleText(context);
for (int i=0; i<N && !mStopped; i++) {
// This builds the icon bitmaps.
mAllAppsList.add(AppInfoCache.cache(apps.get(i), context, bubble));
mAllAppsList.add(new ApplicationInfo(apps.get(i), mIconCache));
}
Collections.sort(mAllAppsList.data, APP_NAME_COMPARATOR);
Collections.sort(mAllAppsList.added, APP_NAME_COMPARATOR);
@@ -1050,9 +1061,9 @@ public class LauncherModel extends BroadcastReceiver {
}
/**
* Make an ApplicationInfo object for an application.
* Make an ShortcutInfo object for a sortcut that is an application.
*/
private static ApplicationInfo getApplicationInfo(PackageManager manager, Intent intent,
public ShortcutInfo getShortcutInfo(PackageManager manager, Intent intent,
Context context) {
final ResolveInfo resolveInfo = manager.resolveActivity(intent, 0);
@@ -1060,26 +1071,26 @@ public class LauncherModel extends BroadcastReceiver {
return null;
}
final ApplicationInfo info = new ApplicationInfo();
final ShortcutInfo info = new ShortcutInfo();
final ActivityInfo activityInfo = resolveInfo.activityInfo;
info.icon = Utilities.createIconThumbnail(activityInfo.loadIcon(manager), context);
info.setIcon(mIconCache.getIcon(intent.getComponent(), resolveInfo));
if (info.title == null || info.title.length() == 0) {
info.title = activityInfo.loadLabel(manager);
}
if (info.title == null) {
info.title = "";
info.title = activityInfo.name;
}
info.itemType = LauncherSettings.Favorites.ITEM_TYPE_APPLICATION;
return info;
}
/**
* Make an ApplicationInfo object for a sortcut
* Make an ShortcutInfo object for a shortcut that isn't an application.
*/
private static ApplicationInfo getApplicationInfoShortcut(Cursor c, Context context,
private ShortcutInfo getShortcutInfo(Cursor c, Context context,
int iconTypeIndex, int iconPackageIndex, int iconResourceIndex, int iconIndex) {
final ApplicationInfo info = new ApplicationInfo();
final ShortcutInfo info = new ShortcutInfo();
info.itemType = LauncherSettings.Favorites.ITEM_TYPE_SHORTCUT;
int iconType = c.getInt(iconTypeIndex);
@@ -1091,9 +1102,9 @@ public class LauncherModel extends BroadcastReceiver {
try {
Resources resources = packageManager.getResourcesForApplication(packageName);
final int id = resources.getIdentifier(resourceName, null, null);
info.icon = Utilities.createIconThumbnail(resources.getDrawable(id), context);
info.setIcon(Utilities.createIconBitmap(resources.getDrawable(id), context));
} catch (Exception e) {
info.icon = packageManager.getDefaultActivityIcon();
info.setIcon(getDefaultIcon());
}
info.iconResource = new Intent.ShortcutIconResource();
info.iconResource.packageName = packageName;
@@ -1104,23 +1115,74 @@ public class LauncherModel extends BroadcastReceiver {
byte[] data = c.getBlob(iconIndex);
try {
Bitmap bitmap = BitmapFactory.decodeByteArray(data, 0, data.length);
info.icon = new FastBitmapDrawable(
Utilities.createBitmapThumbnail(bitmap, context));
info.setIcon(bitmap);
} catch (Exception e) {
packageManager = context.getPackageManager();
info.icon = packageManager.getDefaultActivityIcon();
info.setIcon(getDefaultIcon());
}
info.filtered = true;
info.customIcon = true;
break;
default:
info.icon = context.getPackageManager().getDefaultActivityIcon();
info.setIcon(getDefaultIcon());
info.customIcon = false;
break;
}
return info;
}
ShortcutInfo addShortcut(Context context, Intent data,
CellLayout.CellInfo cellInfo, boolean notify) {
final ShortcutInfo info = infoFromShortcutIntent(context, data);
addItemToDatabase(context, info, LauncherSettings.Favorites.CONTAINER_DESKTOP,
cellInfo.screen, cellInfo.cellX, cellInfo.cellY, notify);
return info;
}
private ShortcutInfo infoFromShortcutIntent(Context context, Intent data) {
Intent intent = data.getParcelableExtra(Intent.EXTRA_SHORTCUT_INTENT);
String name = data.getStringExtra(Intent.EXTRA_SHORTCUT_NAME);
Parcelable bitmap = data.getParcelableExtra(Intent.EXTRA_SHORTCUT_ICON);
Bitmap icon = null;
boolean filtered = false;
boolean customIcon = false;
ShortcutIconResource iconResource = null;
if (bitmap != null && bitmap instanceof Bitmap) {
icon = Utilities.createIconBitmap(new FastBitmapDrawable((Bitmap)bitmap), context);
filtered = true;
customIcon = true;
} else {
Parcelable extra = data.getParcelableExtra(Intent.EXTRA_SHORTCUT_ICON_RESOURCE);
if (extra != null && extra instanceof ShortcutIconResource) {
try {
iconResource = (ShortcutIconResource) extra;
final PackageManager packageManager = context.getPackageManager();
Resources resources = packageManager.getResourcesForApplication(
iconResource.packageName);
final int id = resources.getIdentifier(iconResource.resourceName, null, null);
icon = Utilities.createIconBitmap(resources.getDrawable(id), context);
} catch (Exception e) {
Log.w(TAG, "Could not load shortcut icon: " + extra);
}
}
}
if (icon == null) {
icon = getDefaultIcon();
}
final ShortcutInfo info = new ShortcutInfo();
info.setIcon(icon);
info.title = name;
info.intent = intent;
info.customIcon = customIcon;
info.iconResource = iconResource;
return info;
}
private static void loadLiveFolderIcon(Context context, Cursor c, int iconTypeIndex,
int iconPackageIndex, int iconResourceIndex, LiveFolderInfo liveFolderInfo) {
@@ -1133,18 +1195,21 @@ public class LauncherModel extends BroadcastReceiver {
try {
Resources resources = packageManager.getResourcesForApplication(packageName);
final int id = resources.getIdentifier(resourceName, null, null);
liveFolderInfo.icon = resources.getDrawable(id);
liveFolderInfo.icon = Utilities.createIconBitmap(resources.getDrawable(id),
context);
} catch (Exception e) {
liveFolderInfo.icon =
context.getResources().getDrawable(R.drawable.ic_launcher_folder);
liveFolderInfo.icon = Utilities.createIconBitmap(
context.getResources().getDrawable(R.drawable.ic_launcher_folder),
context);
}
liveFolderInfo.iconResource = new Intent.ShortcutIconResource();
liveFolderInfo.iconResource.packageName = packageName;
liveFolderInfo.iconResource.resourceName = resourceName;
break;
default:
liveFolderInfo.icon =
context.getResources().getDrawable(R.drawable.ic_launcher_folder);
liveFolderInfo.icon = Utilities.createIconBitmap(
context.getResources().getDrawable(R.drawable.ic_launcher_folder),
context);
}
}
@@ -34,9 +34,12 @@ import android.content.pm.PackageManager;
import android.content.pm.ActivityInfo;
import android.database.sqlite.SQLiteOpenHelper;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteStatement;
import android.database.sqlite.SQLiteQueryBuilder;
import android.database.Cursor;
import android.database.SQLException;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.util.Log;
import android.util.Xml;
import android.util.AttributeSet;
@@ -61,7 +64,7 @@ public class LauncherProvider extends ContentProvider {
private static final String DATABASE_NAME = "launcher.db";
private static final int DATABASE_VERSION = 7;
private static final int DATABASE_VERSION = 8;
static final String AUTHORITY = "com.android.launcher2.settings";
@@ -392,6 +395,14 @@ public class LauncherProvider extends ContentProvider {
version = 7;
}
if (version < 8) {
// Version 8 (froyo) has the icons all normalized. This should
// already be the case in practice, but we now rely on it and don't
// resample the images each time.
normalizeIcons(db);
version = 8;
}
if (version != DATABASE_VERSION) {
Log.w(TAG, "Destroying all old data.");
db.execSQL("DROP TABLE IF EXISTS " + TABLE_FAVORITES);
@@ -466,6 +477,60 @@ public class LauncherProvider extends ContentProvider {
return true;
}
private void normalizeIcons(SQLiteDatabase db) {
Log.d(TAG, "normalizing icons");
Cursor c = null;
try {
boolean logged = false;
final ContentValues values = new ContentValues();
final ContentResolver cr = mContext.getContentResolver();
final SQLiteStatement update = db.compileStatement("UPDATE favorites "
+ "WHERE _id=? SET icon=?");
c = db.rawQuery("SELECT _id, icon FROM favorites WHERE iconType=" +
Favorites.ICON_TYPE_BITMAP, null);
final int idIndex = c.getColumnIndexOrThrow(Favorites._ID);
final int iconIndex = c.getColumnIndexOrThrow(Favorites.ICON);
while (c.moveToNext()) {
long id = c.getLong(idIndex);
byte[] data = c.getBlob(iconIndex);
try {
Bitmap bitmap = Utilities.resampleIconBitmap(
BitmapFactory.decodeByteArray(data, 0, data.length),
mContext);
if (bitmap != null) {
update.bindLong(1, id);
data = ItemInfo.flattenBitmap(bitmap);
if (data != null) {
update.bindBlob(2, data);
update.execute();
}
bitmap.recycle();
bitmap = null;
}
} catch (Exception e) {
if (!logged) {
Log.e(TAG, "Failed normalizing icon " + id, e);
} else {
Log.e(TAG, "Also failed normalizing icon " + id);
}
logged = true;
}
}
} catch (SQLException ex) {
Log.w(TAG, "Problem while allocating appWidgetIds for existing widgets", ex);
} finally {
db.endTransaction();
if (c != null) {
c.close();
}
}
}
/**
* Upgrade existing clock and photo frame widgets into their new widget
* equivalents.
@@ -141,7 +141,12 @@ class LiveFolderAdapter extends CursorAdapter {
if (icon == null) {
final Bitmap bitmap = BitmapFactory.decodeByteArray(data, 0, data.length);
icon = new FastBitmapDrawable(Utilities.createBitmapThumbnail(bitmap, mContext));
final Bitmap resampled = Utilities.resampleIconBitmap(bitmap, mContext);
if (bitmap != resampled) {
// If we got back a different object, we don't need the old one any more.
bitmap.recycle();
}
icon = new FastBitmapDrawable(resampled);
mCustomIcons.put(holder.id, new SoftReference<Drawable>(icon));
}
} else if (holder.iconResourceIndex != -1 && holder.iconPackageIndex != -1) {
@@ -154,7 +159,8 @@ class LiveFolderAdapter extends CursorAdapter {
cursor.getString(holder.iconPackageIndex));
final int id = resources.getIdentifier(resource,
null, null);
icon = Utilities.createIconThumbnail(resources.getDrawable(id), mContext);
icon = new FastBitmapDrawable(
Utilities.createIconBitmap(resources.getDrawable(id), mContext));
mIcons.put(resource, icon);
} catch (Exception e) {
// Ignore
@@ -21,7 +21,7 @@ import android.content.res.Resources;
import android.util.AttributeSet;
import android.view.ViewGroup;
import android.view.LayoutInflater;
import android.graphics.drawable.Drawable;
import android.graphics.Bitmap;
public class LiveFolderIcon extends FolderIcon {
public LiveFolderIcon(Context context, AttributeSet attrs) {
@@ -39,13 +39,12 @@ public class LiveFolderIcon extends FolderIcon {
LayoutInflater.from(launcher).inflate(resId, group, false);
final Resources resources = launcher.getResources();
Drawable d = folderInfo.icon;
if (d == null) {
d = Utilities.createIconThumbnail(resources.getDrawable(R.drawable.ic_launcher_folder),
Bitmap b = folderInfo.icon;
if (b == null) {
b = Utilities.createIconBitmap(resources.getDrawable(R.drawable.ic_launcher_folder),
launcher);
folderInfo.filtered = true;
}
icon.setCompoundDrawablesWithIntrinsicBounds(null, d, null, null);
icon.setCompoundDrawablesWithIntrinsicBounds(null, new FastBitmapDrawable(b), null, null);
icon.setText(folderInfo.title);
icon.setTag(folderInfo);
icon.setOnClickListener(launcher);
@@ -19,6 +19,7 @@ package com.android.launcher2;
import android.content.ContentValues;
import android.content.Intent;
import android.graphics.drawable.Drawable;
import android.graphics.Bitmap;
import android.net.Uri;
class LiveFolderInfo extends FolderInfo {
@@ -41,12 +42,7 @@ class LiveFolderInfo extends FolderInfo {
/**
* The live folder icon.
*/
Drawable icon;
/**
* When set to true, indicates that the icon has been resized.
*/
boolean filtered;
Bitmap icon;
/**
* Reference to the live folder icon as an application's resource.
+159
View File
@@ -0,0 +1,159 @@
/*
* Copyright (C) 2008 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.launcher2;
import android.content.ComponentName;
import android.content.ContentValues;
import android.content.Context;
import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.drawable.Drawable;
import android.util.Log;
import java.util.ArrayList;
/**
* Represents a launchable icon on the workspaces and in folders.
*/
class ShortcutInfo extends ItemInfo {
/**
* The application name.
*/
CharSequence title;
/**
* The intent used to start the application.
*/
Intent intent;
/**
* Indicates whether the icon comes from an application's resource (if false)
* or from a custom Bitmap (if true.)
*/
boolean customIcon;
/**
* If isShortcut=true and customIcon=false, this contains a reference to the
* shortcut icon as an application's resource.
*/
Intent.ShortcutIconResource iconResource;
/**
* The application icon.
*/
private Bitmap mIcon;
ShortcutInfo() {
itemType = LauncherSettings.BaseLauncherColumns.ITEM_TYPE_SHORTCUT;
}
public ShortcutInfo(ShortcutInfo info) {
super(info);
title = info.title.toString();
intent = new Intent(info.intent);
if (info.iconResource != null) {
iconResource = new Intent.ShortcutIconResource();
iconResource.packageName = info.iconResource.packageName;
iconResource.resourceName = info.iconResource.resourceName;
}
mIcon = info.mIcon; // TODO: should make a copy here. maybe we don't need this ctor at all
customIcon = info.customIcon;
}
/** TODO: Remove this. It's only called by ApplicationInfo.makeShortcut. */
public ShortcutInfo(ApplicationInfo info) {
super(info);
title = info.title.toString();
intent = new Intent(info.intent);
customIcon = false;
}
public void setIcon(Bitmap b) {
mIcon = b;
}
public Bitmap getIcon(IconCache iconCache) {
if (mIcon == null) {
mIcon = iconCache.getIcon(this.intent);
}
return mIcon;
}
/**
* Creates the application intent based on a component name and various launch flags.
* Sets {@link #itemType} to {@link LauncherSettings.BaseLauncherColumns#ITEM_TYPE_APPLICATION}.
*
* @param className the class name of the component representing the intent
* @param launchFlags the launch flags
*/
final void setActivity(ComponentName className, int launchFlags) {
intent = new Intent(Intent.ACTION_MAIN);
intent.addCategory(Intent.CATEGORY_LAUNCHER);
intent.setComponent(className);
intent.setFlags(launchFlags);
itemType = LauncherSettings.BaseLauncherColumns.ITEM_TYPE_APPLICATION;
}
@Override
void onAddToDatabase(ContentValues values) {
super.onAddToDatabase(values);
String titleStr = title != null ? title.toString() : null;
values.put(LauncherSettings.BaseLauncherColumns.TITLE, titleStr);
String uri = intent != null ? intent.toUri(0) : null;
values.put(LauncherSettings.BaseLauncherColumns.INTENT, uri);
if (customIcon) {
values.put(LauncherSettings.BaseLauncherColumns.ICON_TYPE,
LauncherSettings.BaseLauncherColumns.ICON_TYPE_BITMAP);
Bitmap bitmap = this.mIcon;
writeBitmap(values, bitmap);
} else {
values.put(LauncherSettings.BaseLauncherColumns.ICON_TYPE,
LauncherSettings.BaseLauncherColumns.ICON_TYPE_RESOURCE);
if (iconResource != null) {
values.put(LauncherSettings.BaseLauncherColumns.ICON_PACKAGE,
iconResource.packageName);
values.put(LauncherSettings.BaseLauncherColumns.ICON_RESOURCE,
iconResource.resourceName);
}
}
}
@Override
public String toString() {
return title.toString();
}
@Override
void unbind() {
super.unbind();
}
public static void dumpShortcutInfoList(String tag, String label,
ArrayList<ShortcutInfo> list) {
Log.d(tag, label + " size=" + list.size());
for (ShortcutInfo info: list) {
Log.d(tag, " title=\"" + info.title + " icon=" + info.mIcon
+ " customIcon=" + info.customIcon);
}
}
}
@@ -29,34 +29,29 @@ import java.util.ArrayList;
/**
* GridView adapter to show the list of applications and shortcuts
*/
public class ApplicationsAdapter extends ArrayAdapter<ApplicationInfo> {
public class ShortcutsAdapter extends ArrayAdapter<ShortcutInfo> {
private final LayoutInflater mInflater;
private final PackageManager mPackageManager;
private final IconCache mIconCache;
public ApplicationsAdapter(Context context, ArrayList<ApplicationInfo> apps) {
public ShortcutsAdapter(Context context, ArrayList<ShortcutInfo> apps) {
super(context, 0, apps);
mPackageManager = context.getPackageManager();
mInflater = LayoutInflater.from(context);
mIconCache = ((LauncherApplication)context.getApplicationContext()).getIconCache();
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
final ApplicationInfo info = getItem(position);
final ShortcutInfo info = getItem(position);
if (convertView == null) {
convertView = mInflater.inflate(R.layout.application_boxed, parent, false);
}
if (info.icon == null) {
info.icon = AppInfoCache.getIconDrawable(mPackageManager, info);
}
if (!info.filtered) {
info.icon = Utilities.createIconThumbnail(info.icon, getContext());
info.filtered = true;
}
final TextView textView = (TextView) convertView;
textView.setCompoundDrawablesWithIntrinsicBounds(null, info.icon, null, null);
textView.setCompoundDrawablesWithIntrinsicBounds(null,
new FastBitmapDrawable(info.getIcon(mIconCache)), null, null);
textView.setText(info.title);
return convertView;
+8 -9
View File
@@ -46,13 +46,14 @@ public class UserFolder extends Folder implements DropTarget {
public void onDrop(DragSource source, int x, int y, int xOffset, int yOffset,
DragView dragView, Object dragInfo) {
ApplicationInfo item = (ApplicationInfo) dragInfo;
if (item.container == NO_ID) {
ShortcutInfo item;
if (dragInfo instanceof ApplicationInfo) {
// Came from all apps -- make a copy
item = new ApplicationInfo((ApplicationInfo)item);
item = ((ApplicationInfo)dragInfo).makeShortcut();
} else {
item = (ShortcutInfo)dragInfo;
}
//noinspection unchecked
((ArrayAdapter<ApplicationInfo>) mContent.getAdapter()).add((ApplicationInfo) dragInfo);
((ShortcutsAdapter)mContent.getAdapter()).add(item);
LauncherModel.addOrMoveItemInDatabase(mLauncher, item, mInfo.id, 0, 0, 0);
}
@@ -71,16 +72,14 @@ public class UserFolder extends Folder implements DropTarget {
@Override
public void onDropCompleted(View target, boolean success) {
if (success) {
//noinspection unchecked
ArrayAdapter<ApplicationInfo> adapter =
(ArrayAdapter<ApplicationInfo>) mContent.getAdapter();
ShortcutsAdapter adapter = (ShortcutsAdapter)mContent.getAdapter();
adapter.remove(mDragItem);
}
}
void bind(FolderInfo info) {
super.bind(info);
setContentAdapter(new ApplicationsAdapter(mContext, ((UserFolderInfo) info).contents));
setContentAdapter(new ShortcutsAdapter(mContext, ((UserFolderInfo) info).contents));
}
// When the folder opens, we need to refresh the GridView's selection by
@@ -27,7 +27,7 @@ class UserFolderInfo extends FolderInfo {
/**
* The apps and shortcuts
*/
ArrayList<ApplicationInfo> contents = new ArrayList<ApplicationInfo>();
ArrayList<ShortcutInfo> contents = new ArrayList<ShortcutInfo>();
UserFolderInfo() {
itemType = LauncherSettings.Favorites.ITEM_TYPE_USER_FOLDER;
@@ -38,7 +38,7 @@ class UserFolderInfo extends FolderInfo {
*
* @param item
*/
public void add(ApplicationInfo item) {
public void add(ShortcutInfo item) {
contents.add(item);
}
@@ -47,7 +47,7 @@ class UserFolderInfo extends FolderInfo {
*
* @param item
*/
public void remove(ApplicationInfo item) {
public void remove(ShortcutInfo item) {
contents.remove(item);
}
+6 -125
View File
@@ -85,87 +85,6 @@ final class Utilities {
return bitmap;
}
/**
* Returns a Drawable representing the thumbnail of the specified Drawable.
* The size of the thumbnail is defined by the dimension
* android.R.dimen.launcher_application_icon_size.
*
* @param icon The icon to get a thumbnail of.
* @param context The application's context.
*
* @return A thumbnail for the specified icon or the icon itself if the
* thumbnail could not be created.
*/
static Drawable createIconThumbnail(Drawable icon, Context context) {
synchronized (sCanvas) { // we share the statics :-(
if (sIconWidth == -1) {
initStatics(context);
}
int width = sIconWidth;
int height = sIconHeight;
if (icon instanceof PaintDrawable) {
PaintDrawable painter = (PaintDrawable) icon;
painter.setIntrinsicWidth(width);
painter.setIntrinsicHeight(height);
} else if (icon instanceof BitmapDrawable) {
// Ensure the bitmap has a density.
BitmapDrawable bitmapDrawable = (BitmapDrawable) icon;
Bitmap bitmap = bitmapDrawable.getBitmap();
if (bitmap.getDensity() == Bitmap.DENSITY_NONE) {
bitmapDrawable.setTargetDensity(context.getResources().getDisplayMetrics());
}
}
int iconWidth = icon.getIntrinsicWidth();
int iconHeight = icon.getIntrinsicHeight();
if (iconWidth > 0 && iconHeight > 0) {
if (width < iconWidth || height < iconHeight) {
final float ratio = (float) iconWidth / iconHeight;
if (iconWidth > iconHeight) {
height = (int) (width / ratio);
} else if (iconHeight > iconWidth) {
width = (int) (height * ratio);
}
final Bitmap.Config c = icon.getOpacity() != PixelFormat.OPAQUE ?
Bitmap.Config.ARGB_8888 : Bitmap.Config.RGB_565;
final Bitmap thumb = Bitmap.createBitmap(sIconWidth, sIconHeight, c);
final Canvas canvas = sCanvas;
canvas.setBitmap(thumb);
// Copy the old bounds to restore them later
// If we were to do oldBounds = icon.getBounds(),
// the call to setBounds() that follows would
// change the same instance and we would lose the
// old bounds
sOldBounds.set(icon.getBounds());
final int x = (sIconWidth - width) / 2;
final int y = (sIconHeight - height) / 2;
icon.setBounds(x, y, x + width, y + height);
icon.draw(canvas);
icon.setBounds(sOldBounds);
icon = new FastBitmapDrawable(thumb);
} else if (iconWidth < width && iconHeight < height) {
final Bitmap.Config c = Bitmap.Config.ARGB_8888;
final Bitmap thumb = Bitmap.createBitmap(sIconWidth, sIconHeight, c);
final Canvas canvas = sCanvas;
canvas.setBitmap(thumb);
sOldBounds.set(icon.getBounds());
final int x = (width - iconWidth) / 2;
final int y = (height - iconHeight) / 2;
icon.setBounds(x, y, x + iconWidth, y + iconHeight);
icon.draw(canvas);
icon.setBounds(sOldBounds);
icon = new FastBitmapDrawable(thumb);
}
}
return icon;
}
}
static int sColors[] = { 0xffff0000, 0xff00ff00, 0xff0000ff };
static int sColorIndex = 0;
@@ -173,7 +92,7 @@ final class Utilities {
* Returns a bitmap suitable for the all apps view. The bitmap will be a power
* of two sized ARGB_8888 bitmap that can be used as a gl texture.
*/
static Bitmap createAllAppsBitmap(Drawable icon, Context context) {
static Bitmap createIconBitmap(Drawable icon, Context context) {
synchronized (sCanvas) { // we share the statics :-(
if (sIconWidth == -1) {
initStatics(context);
@@ -279,55 +198,17 @@ final class Utilities {
* @return A thumbnail for the specified bitmap or the bitmap itself if the
* thumbnail could not be created.
*/
static Bitmap createBitmapThumbnail(Bitmap bitmap, Context context) {
static Bitmap resampleIconBitmap(Bitmap bitmap, Context context) {
synchronized (sCanvas) { // we share the statics :-(
if (sIconWidth == -1) {
initStatics(context);
}
int width = sIconWidth;
int height = sIconHeight;
final int bitmapWidth = bitmap.getWidth();
final int bitmapHeight = bitmap.getHeight();
if (width > 0 && height > 0) {
if (width < bitmapWidth || height < bitmapHeight) {
final float ratio = (float) bitmapWidth / bitmapHeight;
if (bitmapWidth > bitmapHeight) {
height = (int) (width / ratio);
} else if (bitmapHeight > bitmapWidth) {
width = (int) (height * ratio);
}
final Bitmap.Config c = (width == sIconWidth && height == sIconHeight) ?
bitmap.getConfig() : Bitmap.Config.ARGB_8888;
final Bitmap thumb = Bitmap.createBitmap(sIconWidth, sIconHeight, c);
final Canvas canvas = sCanvas;
final Paint paint = sPaint;
canvas.setBitmap(thumb);
paint.setDither(false);
paint.setFilterBitmap(true);
sBounds.set((sIconWidth - width) / 2, (sIconHeight - height) / 2, width, height);
sOldBounds.set(0, 0, bitmapWidth, bitmapHeight);
canvas.drawBitmap(bitmap, sOldBounds, sBounds, paint);
return thumb;
} else if (bitmapWidth < width || bitmapHeight < height) {
final Bitmap.Config c = Bitmap.Config.ARGB_8888;
final Bitmap thumb = Bitmap.createBitmap(sIconWidth, sIconHeight, c);
final Canvas canvas = sCanvas;
final Paint paint = sPaint;
canvas.setBitmap(thumb);
paint.setDither(false);
paint.setFilterBitmap(true);
canvas.drawBitmap(bitmap, (sIconWidth - bitmapWidth) / 2,
(sIconHeight - bitmapHeight) / 2, paint);
return thumb;
}
if (bitmap.getWidth() == sIconWidth && bitmap.getHeight() == sIconHeight) {
return bitmap;
} else {
return createIconBitmap(new BitmapDrawable(bitmap), context);
}
return bitmap;
}
}
+19 -22
View File
@@ -90,6 +90,7 @@ public class Workspace extends ViewGroup implements DropTarget, DragSource, Drag
private OnLongClickListener mLongClickListener;
private Launcher mLauncher;
private IconCache mIconCache;
private DragController mDragController;
/**
@@ -142,9 +143,12 @@ public class Workspace extends ViewGroup implements DropTarget, DragSource, Drag
* Initializes various states for this workspace.
*/
private void initWorkspace() {
mScroller = new Scroller(getContext());
Context context = getContext();
mScroller = new Scroller(context);
mCurrentScreen = mDefaultScreen;
Launcher.setScreen(mCurrentScreen);
LauncherApplication app = (LauncherApplication)context.getApplicationContext();
mIconCache = app.getIconCache();
final ViewConfiguration configuration = ViewConfiguration.get(getContext());
mTouchSlop = configuration.getScaledTouchSlop();
@@ -880,11 +884,11 @@ public class Workspace extends ViewGroup implements DropTarget, DragSource, Drag
}
}
void addApplicationShortcut(ApplicationInfo info, CellLayout.CellInfo cellInfo) {
void addApplicationShortcut(ShortcutInfo info, CellLayout.CellInfo cellInfo) {
addApplicationShortcut(info, cellInfo, false);
}
void addApplicationShortcut(ApplicationInfo info, CellLayout.CellInfo cellInfo,
void addApplicationShortcut(ShortcutInfo info, CellLayout.CellInfo cellInfo,
boolean insertAtFirst) {
final CellLayout layout = (CellLayout) getChildAt(cellInfo.screen);
final int[] result = new int[2];
@@ -950,10 +954,9 @@ public class Workspace extends ViewGroup implements DropTarget, DragSource, Drag
case LauncherSettings.Favorites.ITEM_TYPE_SHORTCUT:
if (info.container == NO_ID) {
// Came from all apps -- make a copy
info = new ApplicationInfo((ApplicationInfo) info);
info = new ShortcutInfo((ShortcutInfo)info);
}
view = mLauncher.createShortcut(R.layout.application, cellLayout,
(ApplicationInfo) info);
view = mLauncher.createShortcut(R.layout.application, cellLayout, (ShortcutInfo)info);
break;
case LauncherSettings.Favorites.ITEM_TYPE_USER_FOLDER:
view = FolderIcon.fromXml(R.layout.folder_icon, mLauncher,
@@ -1183,8 +1186,8 @@ public class Workspace extends ViewGroup implements DropTarget, DragSource, Drag
final View view = layout.getChildAt(j);
Object tag = view.getTag();
if (tag instanceof ApplicationInfo) {
final ApplicationInfo info = (ApplicationInfo) tag;
if (tag instanceof ShortcutInfo) {
final ShortcutInfo info = (ShortcutInfo) tag;
// We need to check for ACTION_MAIN otherwise getComponent() might
// return null for some shortcuts (for instance, for shortcuts to
// web pages.)
@@ -1199,14 +1202,13 @@ public class Workspace extends ViewGroup implements DropTarget, DragSource, Drag
}
} else if (tag instanceof UserFolderInfo) {
final UserFolderInfo info = (UserFolderInfo) tag;
final ArrayList<ApplicationInfo> contents = info.contents;
final ArrayList<ApplicationInfo> toRemove =
new ArrayList<ApplicationInfo>(1);
final ArrayList<ShortcutInfo> contents = info.contents;
final ArrayList<ShortcutInfo> toRemove = new ArrayList<ShortcutInfo>(1);
final int contentsCount = contents.size();
boolean removedFromFolder = false;
for (int k = 0; k < contentsCount; k++) {
final ApplicationInfo appInfo = contents.get(k);
final ShortcutInfo appInfo = contents.get(k);
final Intent intent = appInfo.intent;
final ComponentName name = intent.getComponent();
@@ -1277,8 +1279,8 @@ public class Workspace extends ViewGroup implements DropTarget, DragSource, Drag
for (int j = 0; j < childCount; j++) {
final View view = layout.getChildAt(j);
Object tag = view.getTag();
if (tag instanceof ApplicationInfo) {
ApplicationInfo info = (ApplicationInfo) tag;
if (tag instanceof ShortcutInfo) {
ShortcutInfo info = (ShortcutInfo)tag;
// We need to check for ACTION_MAIN otherwise getComponent() might
// return null for some shortcuts (for instance, for shortcuts to
// web pages.)
@@ -1288,14 +1290,9 @@ public class Workspace extends ViewGroup implements DropTarget, DragSource, Drag
Intent.ACTION_MAIN.equals(intent.getAction()) && name != null &&
packageName.equals(name.getPackageName())) {
final Drawable icon = AppInfoCache.getIconDrawable(pm, info);
if (icon != null && icon != info.icon) {
info.icon.setCallback(null);
info.icon = Utilities.createIconThumbnail(icon, mContext);
info.filtered = true;
((TextView) view).setCompoundDrawablesWithIntrinsicBounds(null,
info.icon, null, null);
}
info.setIcon(mIconCache.getIcon(info.intent));
((TextView) view).setCompoundDrawablesWithIntrinsicBounds(null,
new FastBitmapDrawable(info.getIcon(mIconCache)), null, null);
}
}
}