Commit 56ca86b7 authored by Mathew Inwood's avatar Mathew Inwood
Browse files

Merge remote-tracking branch 'goog/ub-now-lunchbox' into lunchbox-release

parents 07130d40 0e4a365e
<?xml version="1.0" encoding="utf-8"?>
<!--
/*
* Copyright (C) 2013 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.
*/
-->
<resources>
<style name="Theme" parent="android:Theme.Holo.Wallpaper.NoTitleBar">
<item name="android:windowActionModeOverlay">true</item>
<item name="android:windowTranslucentStatus">true</item>
<item name="android:windowTranslucentNavigation">true</item>
</style>
</resources>
......@@ -20,7 +20,5 @@
<resources>
<style name="Theme" parent="android:Theme.Holo.Wallpaper.NoTitleBar">
<item name="android:windowActionModeOverlay">true</item>
<item name="android:windowTranslucentStatus">true</item>
<item name="android:windowTranslucentNavigation">true</item>
</style>
</resources>
<?xml version="1.0" encoding="utf-8"?>
<!--
/*
* Copyright (C) 2013 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.
*/
-->
<resources>
<style name="Theme.WallpaperCropper" parent="@android:style/Theme.Holo">
<item name="android:actionBarStyle">@style/WallpaperCropperActionBar</item>
<item name="android:windowFullscreen">true</item>
<item name="android:windowActionBarOverlay">true</item>
<item name="android:windowTranslucentNavigation">true</item>
</style>
<style name="Theme" parent="@android:style/Theme.Holo.Wallpaper.NoTitleBar">
<item name="android:windowTranslucentStatus">true</item>
<item name="android:windowTranslucentNavigation">true</item>
</style>
</resources>
......@@ -22,7 +22,6 @@
<item name="android:actionBarStyle">@style/WallpaperCropperActionBar</item>
<item name="android:windowFullscreen">true</item>
<item name="android:windowActionBarOverlay">true</item>
<item name="android:windowTranslucentNavigation">true</item>
</style>
<style name="WallpaperCropperActionBar" parent="android:style/Widget.Holo.ActionBar">
......@@ -31,7 +30,5 @@
</style>
<style name="Theme" parent="@android:style/Theme.Holo.Wallpaper.NoTitleBar">
<item name="android:windowTranslucentStatus">true</item>
<item name="android:windowTranslucentNavigation">true</item>
</style>
</resources>
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (C) 2012 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.
-->
<!-- dummy layout, to be replaced in overlays -->
<com.android.launcher3.Cling
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:launcher="http://schemas.android.com/apk/res-auto/com.android.launcher3"
android:layout_width="match_parent"
android:layout_height="match_parent"
launcher:drawIdentifier="workspace_custom">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="20dp"
android:textColor="@android:color/holo_blue_light"
android:text="@string/dummy_custom_cling_error_message"
android:gravity="start"
android:layout_gravity="bottom|start"
/>
</com.android.launcher3.Cling>
......@@ -252,18 +252,6 @@ s -->
<!-- Folder name format -->
<string name="folder_name_format">Folder: <xliff:g id="name" example="Games">%1$s</xliff:g></string>
<!-- Strings used in device overlays -->
<!-- Clings -->
<!-- Dummy string [CHAR_LIMIT=40] -->
<string name="custom_workspace_cling_title_1"></string>
<!-- Dummy string [CHAR_LIMIT=60] -->
<string name="custom_workspace_cling_description_1"></string>
<!-- Dummy string [CHAR_LIMIT=40] -->
<string name="custom_workspace_cling_title_2"></string>
<!-- Dummy string [CHAR_LIMIT=60] -->
<string name="custom_workspace_cling_description_2"></string>
<!-- Debug-only activity name. [DO NOT TRANSLATE] -->
<string name="debug_memory_activity">* HPROF</string>
......
......@@ -32,7 +32,7 @@ import java.util.List;
*/
class AllAppsList {
public static final int DEFAULT_APPLICATIONS_NUMBER = 42;
/** The list off all apps. */
public ArrayList<AppInfo> data =
new ArrayList<AppInfo>(DEFAULT_APPLICATIONS_NUMBER);
......@@ -115,8 +115,7 @@ class AllAppsList {
data.remove(i);
}
}
// This is more aggressive than it needs to be.
mIconCache.flush();
mIconCache.remove(packageName);
}
/**
......
......@@ -16,6 +16,8 @@
package com.android.launcher3;
import com.android.launcher3.backup.BackupProtos;
import android.app.ActivityManager;
import android.content.ComponentName;
import android.content.Context;
......@@ -25,10 +27,20 @@ import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.drawable.Drawable;
import android.util.Log;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Map.Entry;
......@@ -40,6 +52,9 @@ public class IconCache {
private static final String TAG = "Launcher.IconCache";
private static final int INITIAL_ICON_CACHE_CAPACITY = 50;
private static final String RESOURCE_FILE_PREFIX = "icon_";
private static final boolean DEBUG = true;
private static class CacheEntry {
public Bitmap icon;
......@@ -115,6 +130,7 @@ public class IconCache {
return getFullResIcon(resources, iconId);
}
}
return getFullResDefaultActivityIcon();
}
......@@ -139,6 +155,21 @@ public class IconCache {
}
}
/**
* Remove any records for the supplied package name.
*/
public void remove(String packageName) {
HashSet<ComponentName> forDeletion = new HashSet<ComponentName>();
for (ComponentName componentName: mCache.keySet()) {
if (componentName.getPackageName().equals(packageName)) {
forDeletion.add(componentName);
}
}
for (ComponentName condemned: forDeletion) {
remove(condemned);
}
}
/**
* Empty out the cache.
*/
......@@ -177,15 +208,22 @@ public class IconCache {
}
public Bitmap getIcon(Intent intent) {
return getIcon(intent, null);
}
public Bitmap getIcon(Intent intent, String title) {
synchronized (mCache) {
final ResolveInfo resolveInfo = mPackageManager.resolveActivity(intent, 0);
ComponentName component = intent.getComponent();
if (resolveInfo == null || component == null) {
if (component == null) {
return mDefaultIcon;
}
CacheEntry entry = cacheLocked(component, resolveInfo, null);
if (title != null) {
entry.title = title;
}
return entry.icon;
}
}
......@@ -214,21 +252,35 @@ public class IconCache {
mCache.put(componentName, entry);
ComponentName key = LauncherModel.getComponentNameFromResolveInfo(info);
if (labelCache != null && labelCache.containsKey(key)) {
entry.title = labelCache.get(key).toString();
if (info != null) {
ComponentName key = LauncherModel.getComponentNameFromResolveInfo(info);
if (labelCache != null && labelCache.containsKey(key)) {
entry.title = labelCache.get(key).toString();
} else {
entry.title = info.loadLabel(mPackageManager).toString();
if (labelCache != null) {
labelCache.put(key, entry.title);
}
}
if (entry.title == null) {
entry.title = info.activityInfo.name;
}
entry.icon = Utilities.createIconBitmap(
getFullResIcon(info), mContext);
} else {
entry.title = info.loadLabel(mPackageManager).toString();
if (labelCache != null) {
labelCache.put(key, entry.title);
entry.title = "";
Bitmap preloaded = getPreloadedIcon(componentName);
if (preloaded != null) {
if (DEBUG) Log.d(TAG, "using preloaded icon for " +
componentName.toShortString());
entry.icon = preloaded;
} else {
if (DEBUG) Log.d(TAG, "using default icon for " +
componentName.toShortString());
entry.icon = mDefaultIcon;
}
}
if (entry.title == null) {
entry.title = info.activityInfo.name;
}
entry.icon = Utilities.createIconBitmap(
getFullResIcon(info), mContext);
}
return entry;
}
......@@ -243,4 +295,137 @@ public class IconCache {
return set;
}
}
/**
* Pre-load an icon into the persistent cache.
*
* <P>Queries for a component that does not exist in the package manager
* will be answered by the persistent cache.
*
* @param context application context
* @param componentName the icon should be returned for this component
* @param icon the icon to be persisted
* @param dpi the native density of the icon
*/
public static void preloadIcon(Context context, ComponentName componentName, Bitmap icon,
int dpi) {
// TODO rescale to the correct native DPI
try {
PackageManager packageManager = context.getPackageManager();
packageManager.getActivityIcon(componentName);
// component is present on the system already, do nothing
return;
} catch (PackageManager.NameNotFoundException e) {
// pass
}
final String key = componentName.flattenToString();
FileOutputStream resourceFile = null;
try {
resourceFile = context.openFileOutput(getResourceFilename(componentName),
Context.MODE_PRIVATE);
ByteArrayOutputStream os = new ByteArrayOutputStream();
if (icon.compress(android.graphics.Bitmap.CompressFormat.PNG, 75, os)) {
byte[] buffer = os.toByteArray();
resourceFile.write(buffer, 0, buffer.length);
} else {
Log.w(TAG, "failed to encode cache for " + key);
return;
}
} catch (FileNotFoundException e) {
Log.w(TAG, "failed to pre-load cache for " + key, e);
} catch (IOException e) {
Log.w(TAG, "failed to pre-load cache for " + key, e);
} finally {
if (resourceFile != null) {
try {
resourceFile.close();
} catch (IOException e) {
Log.d(TAG, "failed to save restored icon for: " + key, e);
}
}
}
}
/**
* Read a pre-loaded icon from the persistent icon cache.
*
* @param componentName the component that should own the icon
* @returns a bitmap if one is cached, or null.
*/
private Bitmap getPreloadedIcon(ComponentName componentName) {
final String key = componentName.flattenToShortString();
if (DEBUG) Log.v(TAG, "looking for pre-load icon for " + key);
Bitmap icon = null;
FileInputStream resourceFile = null;
try {
resourceFile = mContext.openFileInput(getResourceFilename(componentName));
byte[] buffer = new byte[1024];
ByteArrayOutputStream bytes = new ByteArrayOutputStream();
int bytesRead = 0;
while(bytesRead >= 0) {
bytes.write(buffer, 0, bytesRead);
bytesRead = resourceFile.read(buffer, 0, buffer.length);
}
if (DEBUG) Log.d(TAG, "read " + bytes.size());
icon = BitmapFactory.decodeByteArray(bytes.toByteArray(), 0, bytes.size());
if (icon == null) {
Log.w(TAG, "failed to decode pre-load icon for " + key);
}
} catch (FileNotFoundException e) {
if (DEBUG) Log.d(TAG, "there is no restored icon for: " + key, e);
} catch (IOException e) {
Log.w(TAG, "failed to read pre-load icon for: " + key, e);
} finally {
if(resourceFile != null) {
try {
resourceFile.close();
} catch (IOException e) {
Log.d(TAG, "failed to manage pre-load icon file: " + key, e);
}
}
}
if (icon != null) {
// TODO: handle alpha mask in the view layer
Bitmap b = Bitmap.createBitmap(Math.max(icon.getWidth(), 1),
Math.max(icon.getHeight(), 1),
Bitmap.Config.ARGB_8888);
Canvas c = new Canvas(b);
Paint paint = new Paint();
paint.setAlpha(127);
c.drawBitmap(icon, 0, 0, paint);
c.setBitmap(null);
icon.recycle();
icon = b;
}
return icon;
}
/**
* Remove a pre-loaded icon from the persistent icon cache.
*
* @param componentName the component that should own the icon
* @returns true on success
*/
public boolean deletePreloadedIcon(ComponentName componentName) {
if (componentName == null) {
return false;
}
if (mCache.remove(componentName) != null) {
if (DEBUG) Log.d(TAG, "removed pre-loaded icon from the in-memory cache");
}
boolean success = mContext.deleteFile(getResourceFilename(componentName));
if (DEBUG && success) Log.d(TAG, "removed pre-loaded icon from persistent cache");
return success;
}
private static String getResourceFilename(ComponentName component) {
String resourceName = component.flattenToShortString();
String filename = resourceName.replace(File.separatorChar, '_');
return RESOURCE_FILE_PREFIX + filename;
}
}
......@@ -50,7 +50,9 @@ import android.util.Base64;
import android.util.Log;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.net.URISyntaxException;
......@@ -136,6 +138,8 @@ public class LauncherBackupHelper implements BackupHelper {
private static final int SCREEN_RANK_INDEX = 2;
private static IconCache mIconCache;
private final Context mContext;
private final boolean mRestoreEnabled;
......@@ -441,14 +445,12 @@ public class LauncherBackupHelper implements BackupHelper {
private void backupIcons(Journal in, BackupDataOutput data, Journal out,
ArrayList<Key> keys) throws IOException {
// persist icons that haven't been persisted yet
final LauncherAppState appState = LauncherAppState.getInstanceNoCreate();
if (appState == null) {
if (!initializeIconCache()) {
dataChanged(); // try again later
if (DEBUG) Log.d(TAG, "Launcher is not initialized, delaying icon backup");
return;
}
final ContentResolver cr = mContext.getContentResolver();
final IconCache iconCache = appState.getIconCache();
final int dpi = mContext.getResources().getDisplayMetrics().densityDpi;
// read the old ID set
......@@ -487,9 +489,9 @@ public class LauncherBackupHelper implements BackupHelper {
if (DEBUG) Log.d(TAG, "I can count this high: " + out.rows);
if ((out.rows - startRows) < MAX_ICONS_PER_PASS) {
if (VERBOSE) Log.v(TAG, "saving icon " + backupKey);
Bitmap icon = iconCache.getIcon(intent);
Bitmap icon = mIconCache.getIcon(intent);
keys.add(key);
if (icon != null && !iconCache.isDefaultIcon(icon)) {
if (icon != null && !mIconCache.isDefaultIcon(icon)) {
byte[] blob = packIcon(dpi, icon);
writeRowToBackup(key, blob, out, data);
}
......@@ -530,25 +532,33 @@ public class LauncherBackupHelper implements BackupHelper {
if (VERBOSE) Log.v(TAG, "unpacking icon " + key.id);
if (DEBUG) Log.d(TAG, "read (" + buffer.length + "): " +
Base64.encodeToString(buffer, 0, dataSize, Base64.NO_WRAP));
try {
Resource res = unpackIcon(buffer, 0, dataSize);
if (DEBUG) Log.d(TAG, "unpacked " + res.dpi + " dpi icon");
if (DEBUG_PAYLOAD) Log.d(TAG, "read " +
Base64.encodeToString(res.data, 0, res.data.length,
Base64.NO_WRAP));
if (DEBUG) {
Log.d(TAG, "unpacked " + res.dpi + " dpi icon");
}
if (DEBUG_PAYLOAD) {
Log.d(TAG, "read " +
Base64.encodeToString(res.data, 0, res.data.length,
Base64.NO_WRAP));
}
Bitmap icon = BitmapFactory.decodeByteArray(res.data, 0, res.data.length);
if (icon == null) {
Log.w(TAG, "failed to unpack icon for " + key.name);
}
if (!mRestoreEnabled) {
if (VERBOSE) Log.v(TAG, "restore not enabled: skipping database mutation");
if (VERBOSE) {
Log.v(TAG, "restore not enabled: skipping database mutation");
}
return;
} else {
// future site of icon cache mutation
IconCache.preloadIcon(mContext, ComponentName.unflattenFromString(key.name),
icon, res.dpi);
}
} catch (InvalidProtocolBufferNanoException e) {
Log.e(TAG, "failed to decode icon", e);
} catch (IOException e) {
Log.d(TAG, "failed to save restored icon for: " + key.name, e);
}
}
......@@ -566,15 +576,13 @@ public class LauncherBackupHelper implements BackupHelper {
ArrayList<Key> keys) throws IOException {
// persist static widget info that hasn't been persisted yet
final LauncherAppState appState = LauncherAppState.getInstanceNoCreate();
if (appState == null) {
dataChanged(); // try again later
if (DEBUG) Log.d(TAG, "Launcher is not initialized, delaying widget backup");
if (appState == null || !initializeIconCache()) {
Log.w(TAG, "Failed to get icon cache during restore");
return;
}
final ContentResolver cr = mContext.getContentResolver();
final WidgetPreviewLoader previewLoader = new WidgetPreviewLoader(mContext);
final PagedViewCellLayout widgetSpacingLayout = new PagedViewCellLayout(mContext);
final IconCache iconCache = appState.getIconCache();
final int dpi = mContext.getResources().getDisplayMetrics().densityDpi;
final DeviceProfile profile = appState.getDynamicGrid().getDeviceProfile();
if (DEBUG) Log.d(TAG, "cellWidthPx: " + profile.cellWidthPx);
......@@ -617,7 +625,7 @@ public class LauncherBackupHelper implements BackupHelper {
if (VERBOSE) Log.v(TAG, "saving widget " + backupKey);
previewLoader.setPreviewSize(spanX * profile.cellWidthPx,
spanY * profile.cellHeightPx, widgetSpacingLayout);
byte[] blob = packWidget(dpi, previewLoader, iconCache, provider);
byte[] blob = packWidget(dpi, previewLoader, mIconCache, provider);
keys.add(key);
writeRowToBackup(key, blob, out, data);
......@@ -882,7 +890,7 @@ public class LauncherBackupHelper implements BackupHelper {
}
/** Deserialize an icon resource from persistence, after verifying checksum wrapper. */
private Resource unpackIcon(byte[] buffer, int offset, int dataSize)
private static Resource unpackIcon(byte[] buffer, int offset, int dataSize)
throws InvalidProtocolBufferNanoException {
Resource res = new Resource();
MessageNano.mergeFrom(res, readCheckedBytes(buffer, offset, dataSize));
......@@ -1080,7 +1088,7 @@ public class LauncherBackupHelper implements BackupHelper {
}
/** Unwrap a proto message from a CheckedMessage, verifying the checksum. */
private byte[] readCheckedBytes(byte[] buffer, int offset, int dataSize)
private static byte[] readCheckedBytes(byte[] buffer, int offset, int dataSize)
throws InvalidProtocolBufferNanoException {
CheckedMessage wrapper = new CheckedMessage();
MessageNano.mergeFrom(wrapper, buffer, offset, dataSize);
......@@ -1104,6 +1112,23 @@ public class LauncherBackupHelper implements BackupHelper {
return mWidgetMap.get(component);
}
private boolean initializeIconCache() {
if (mIconCache != null) {
return true;
}
final LauncherAppState appState = LauncherAppState.getInstanceNoCreate();
if (appState == null) {
Throwable stackTrace = new Throwable();
stackTrace.fillInStackTrace();
Log.w(TAG, "Failed to get app state during backup/restore", stackTrace);
return false;
}
mIconCache = appState.getIconCache();
return mIconCache != null;
}
private class KeyParsingException extends Throwable {
private KeyParsingException(Throwable cause) {
super(cause);
......
......@@ -41,7 +41,6 @@ class LauncherClings {
private static final String FOLDER_CLING_DISMISSED_KEY = "cling_gel.folder.dismissed";
private static final boolean DISABLE_CLINGS = false;
private static final boolean DISABLE_CUSTOM_CLINGS = true;
private static final int SHOW_CLING_DURATION = 250;
private static final int DISMISS_CLING_DURATION = 200;
......@@ -196,8 +195,7 @@ class LauncherClings {
SharedPreferences sharedPrefs = mLauncher.getSharedPrefs();
return areClingsEnabled() &&
!sharedPrefs.getBoolean(FIRST_RUN_CLING_DISMISSED_KEY, false) &&
!sharedPrefs.getBoolean(MIGRATION_CLING_DISMISSED_KEY, false) &&
LauncherAppState.getLauncherProvider().wasNewDbCreated();
!sharedPrefs.getBoolean(MIGRATION_CLING_DISMISSED_KEY, false);
}
public void removeFirstRunAndMigrationClings() {
......@@ -213,24 +211,6 @@ class LauncherClings {
*/
public void showFirstRunCling() {
if (!skipCustomClingIfNoAccounts()) {
SharedPreferences sharedPrefs = mLauncher.getSharedPrefs();
// If we're not using the default workspace layout, replace workspace cling
// with a custom workspace cling (usually specified in an overlay)
// For now, only do this on tablets
if (!DISABLE_CUSTOM_CLINGS) {
if (sharedPrefs.getInt(LauncherProvider.DEFAULT_WORKSPACE_RESOURCE_ID, 0) != 0 &&
mLauncher.getResources().getBoolean(R.bool.config_useCustomClings)) {
// Use a custom cling
View cling = mLauncher.findViewById(R.id.workspace_cling);
ViewGroup clingParent = (ViewGroup) cling.getParent();
int clingIndex = clingParent.indexOfChild(cling);
clingParent.removeViewAt(clingIndex);
View customCling = mInflater.inflate(R.layout.custom_workspace_cling,
clingParent, false);
clingParent.addView(customCling, clingIndex);
customCling.setId(R.id.workspace_cling);
}
}
Cling cling = (Cling) mLauncher.findViewById(R.id.first_run_cling);
if (cling != null) {
String sbHintStr = mLauncher.getFirstRunClingSearchBarHint();
......@@ -292,6 +272,7 @@ class LauncherClings {
removeCling(R.id.workspace_cling);
}
}
public Cling showFoldersCling() {
SharedPreferences sharedPrefs = mLauncher.getSharedPrefs();
// Enable the clings only if they have not been dismissed before
......@@ -314,6 +295,14 @@ class LauncherClings {
}
}
public static void synchonouslyMarkFirstRunClingDismissed(Context ctx) {
SharedPreferences prefs = ctx.getSharedPreferences(
LauncherAppState.getSharedPreferencesKey(),Context.MODE_PRIVATE);
SharedPreferences.Editor editor = prefs.edit();
editor.putBoolean(LauncherClings.FIRST_RUN_CLING_DISMISSED_KEY, true);
editor.commit();
}
/** Removes the cling outright from the DragLayer */
private void removeCling(int id) {
final View cling = mLauncher.findViewById(id);
......@@ -453,4 +442,4 @@ class LauncherClings {
dismissCling(cling, null, FOLDER_CLING_DISMISSED_KEY,
DISMISS_CLING_DURATION, true);
}
}
\ No newline at end of file
}
......@@ -318,10 +318,16 @@ public class LauncherModel extends BroadcastReceiver {
public void run() {
Callbacks cb = mCallbacks != null ? mCallbacks.get() : null;
if (callbacks == cb && cb != null) {
callbacks.bindAppsAdded(null, null, null, allAppsApps);
if (!restoredAppsFinal.isEmpty()) {
for (AppInfo info : restoredAppsFinal) {
final Intent intent = info.getIntent();
if (intent != null) {
mIconCache.deletePreloadedIcon(intent.getComponent());
}
}
callbacks.bindAppsUpdated(restoredAppsFinal);
}
callbacks.bindAppsAdded(null, null, null, allAppsApps);
}
}
});
......@@ -2667,6 +2673,7 @@ public class LauncherModel extends BroadcastReceiver {
case OP_ADD:
for (int i=0; i<N; i++) {
if (DEBUG_LOADERS) Log.d(TAG, "mAllAppsList.addPackage " + packages[i]);
mIconCache.remove(packages[i]);
mBgAllAppsList.addPackage(context, packages[i]);
}
break;
......@@ -2862,13 +2869,12 @@ public class LauncherModel extends BroadcastReceiver {
*/
public ShortcutInfo getRestoredItemInfo(Cursor cursor, int titleIndex, Intent intent) {
final ShortcutInfo info = new ShortcutInfo();
info.usingFallbackIcon = true;
info.setIcon(getFallbackIcon());
if (cursor != null) {
info.title = cursor.getString(titleIndex);
} else {
info.title = "";
}
info.setIcon(mIconCache.getIcon(intent, info.title.toString()));
info.itemType = LauncherSettings.Favorites.ITEM_TYPE_SHORTCUT;
info.restoredIntent = intent;
return info;
......
......@@ -71,7 +71,7 @@ public class LauncherProvider extends ContentProvider {
private static final String DATABASE_NAME = "launcher.db";
private static final int DATABASE_VERSION = 16;
private static final int DATABASE_VERSION = 17;
static final String OLD_AUTHORITY = "com.android.launcher2.settings";
static final String AUTHORITY = ProviderConfig.AUTHORITY;
......@@ -769,6 +769,16 @@ public class LauncherProvider extends ContentProvider {
}
}
if (version < 17) {
// We use the db version upgrade here to identify users who may not have seen
// clings yet (because they weren't available), but for whom the clings are now
// available (tablet users). Because one of the possible cling flows (migration)
// is very destructive (wipes out workspaces), we want to prevent this from showing
// until clear data. We do so by marking that the clings have been shown.
LauncherClings.synchonouslyMarkFirstRunClingDismissed(mContext);
version = 17;
}
if (version != DATABASE_VERSION) {
Log.w(TAG, "Destroying all old data.");
db.execSQL("DROP TABLE IF EXISTS " + TABLE_FAVORITES);
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment