diff options
author | Tony Wickham <twickham@google.com> | 2016-03-17 15:39:39 -0700 |
---|---|---|
committer | Tony Wickham <twickham@google.com> | 2016-04-01 15:40:57 -0700 |
commit | 827cef203f386cb548b98a7fa9888b75478c8e20 (patch) | |
tree | f310b21ce3092156534cf94602a3ecf25283a44e /src/com/android/launcher3 | |
parent | 855b1b5fff5f6f03a641b3b6973780a24fd9641e (diff) | |
download | android_packages_apps_Trebuchet-827cef203f386cb548b98a7fa9888b75478c8e20.tar.gz android_packages_apps_Trebuchet-827cef203f386cb548b98a7fa9888b75478c8e20.tar.bz2 android_packages_apps_Trebuchet-827cef203f386cb548b98a7fa9888b75478c8e20.zip |
Added ColorExtractionService and ExtractedColors.
- Launcher has an instance of ExtractedColors, which is loaded from
LauncherProvider in onCreate() and whenever the wallpaper changes.
- When the wallpaper changes, the ColorExtractionService is started
in the :wallpaper-chooser process.
- ColorExtractionService builds an ExtractedColors instance and saves
it as a String in LauncherProvider.
- When the results are saved, Launcher gets a callback through
LauncherProviderChangeListener and reloads the ExtractedColors.
- Whenever Launcher loads Extractecolors, it also re-colors items
(currently a no-op).
Change-Id: I319e2cfe0a86abcbc6bb39ef6b9fbbcad54ad743
Diffstat (limited to 'src/com/android/launcher3')
-rw-r--r-- | src/com/android/launcher3/Launcher.java | 17 | ||||
-rw-r--r-- | src/com/android/launcher3/LauncherAppState.java | 8 | ||||
-rw-r--r-- | src/com/android/launcher3/LauncherModel.java | 3 | ||||
-rw-r--r-- | src/com/android/launcher3/LauncherProvider.java | 42 | ||||
-rw-r--r-- | src/com/android/launcher3/LauncherProviderChangeListener.java | 2 | ||||
-rw-r--r-- | src/com/android/launcher3/LauncherSettings.java | 5 | ||||
-rw-r--r-- | src/com/android/launcher3/Utilities.java | 4 | ||||
-rw-r--r-- | src/com/android/launcher3/dynamicui/ColorExtractionService.java | 63 | ||||
-rw-r--r-- | src/com/android/launcher3/dynamicui/ExtractedColors.java | 131 | ||||
-rw-r--r-- | src/com/android/launcher3/dynamicui/ExtractionUtils.java | 75 |
10 files changed, 344 insertions, 6 deletions
diff --git a/src/com/android/launcher3/Launcher.java b/src/com/android/launcher3/Launcher.java index b16a6500c..54f026262 100644 --- a/src/com/android/launcher3/Launcher.java +++ b/src/com/android/launcher3/Launcher.java @@ -105,6 +105,7 @@ import com.android.launcher3.config.ProviderConfig; import com.android.launcher3.dragndrop.DragController; import com.android.launcher3.dragndrop.DragLayer; import com.android.launcher3.dragndrop.DragView; +import com.android.launcher3.dynamicui.ExtractedColors; import com.android.launcher3.folder.Folder; import com.android.launcher3.folder.FolderIcon; import com.android.launcher3.logging.LoggerUtils; @@ -279,6 +280,7 @@ public class Launcher extends Activity private LauncherModel mModel; private IconCache mIconCache; + private ExtractedColors mExtractedColors; @Thunk boolean mUserPresent = true; private boolean mVisible = false; private boolean mHasFocus = false; @@ -447,6 +449,8 @@ public class Launcher extends Activity app.getInvariantDeviceProfile().portraitProfile.setSearchBarHeight(getSearchBarHeight()); setupViews(); mDeviceProfile.layout(this); + mExtractedColors = new ExtractedColors(); + loadExtractedColorsAndColorItems(); lockAllApps(); @@ -509,6 +513,19 @@ public class Launcher extends Activity } } + @Override + public void onExtractedColorsChanged() { + loadExtractedColorsAndColorItems(); + } + + private void loadExtractedColorsAndColorItems() { + if (mExtractedColors != null) { + mExtractedColors.load(this); + // TODO: pass mExtractedColors to interested items such as hotseat. + mHotseat.setBackgroundColor(mExtractedColors.getColor(ExtractedColors.VIBRANT_INDEX)); + } + } + private LauncherCallbacks mLauncherCallbacks; public void onPostCreate(Bundle savedInstanceState) { diff --git a/src/com/android/launcher3/LauncherAppState.java b/src/com/android/launcher3/LauncherAppState.java index e58652b8e..302a0c36a 100644 --- a/src/com/android/launcher3/LauncherAppState.java +++ b/src/com/android/launcher3/LauncherAppState.java @@ -28,6 +28,7 @@ import com.android.launcher3.compat.LauncherAppsCompat; import com.android.launcher3.compat.PackageInstallerCompat; import com.android.launcher3.compat.UserManagerCompat; import com.android.launcher3.config.FeatureFlags; +import com.android.launcher3.dynamicui.ExtractionUtils; import com.android.launcher3.util.ConfigMonitor; import com.android.launcher3.util.TestingUtils; import com.android.launcher3.util.Thunk; @@ -108,6 +109,11 @@ public class LauncherAppState { filter.addAction(LauncherAppsCompat.ACTION_MANAGED_PROFILE_ADDED); filter.addAction(LauncherAppsCompat.ACTION_MANAGED_PROFILE_REMOVED); filter.addAction(LauncherAppsCompat.ACTION_MANAGED_PROFILE_AVAILABILITY_CHANGED); + // For extracting colors from the wallpaper + if (Utilities.isNycOrAbove()) { + // TODO: add a broadcast entry to the manifest for pre-N. + filter.addAction(Intent.ACTION_WALLPAPER_CHANGED); + } sContext.registerReceiver(mModel, filter); UserManagerCompat.getInstance(sContext).enableAndResetCache(); @@ -121,6 +127,8 @@ public class LauncherAppState { }, new IntentFilter(Intent.ACTION_WALLPAPER_CHANGED)); } new ConfigMonitor(sContext).register(); + + ExtractionUtils.startColorExtractionServiceIfNecessary(sContext); } /** diff --git a/src/com/android/launcher3/LauncherModel.java b/src/com/android/launcher3/LauncherModel.java index 3c7366cc3..f6a067ca3 100644 --- a/src/com/android/launcher3/LauncherModel.java +++ b/src/com/android/launcher3/LauncherModel.java @@ -54,6 +54,7 @@ import com.android.launcher3.compat.PackageInstallerCompat.PackageInstallInfo; import com.android.launcher3.compat.UserHandleCompat; import com.android.launcher3.compat.UserManagerCompat; import com.android.launcher3.config.ProviderConfig; +import com.android.launcher3.dynamicui.ExtractionUtils; import com.android.launcher3.folder.Folder; import com.android.launcher3.folder.FolderIcon; import com.android.launcher3.model.GridSizeMigrationTask; @@ -1237,6 +1238,8 @@ public class LauncherModel extends BroadcastReceiver PackageUpdatedTask.OP_USER_AVAILABILITY_CHANGE, new String[0], user)); } + } else if (Intent.ACTION_WALLPAPER_CHANGED.equals(action)) { + ExtractionUtils.startColorExtractionServiceIfNecessary(context); } } diff --git a/src/com/android/launcher3/LauncherProvider.java b/src/com/android/launcher3/LauncherProvider.java index 207121b27..f07609480 100644 --- a/src/com/android/launcher3/LauncherProvider.java +++ b/src/com/android/launcher3/LauncherProvider.java @@ -53,6 +53,7 @@ import com.android.launcher3.LauncherSettings.Favorites; import com.android.launcher3.compat.UserHandleCompat; import com.android.launcher3.compat.UserManagerCompat; import com.android.launcher3.config.ProviderConfig; +import com.android.launcher3.dynamicui.ExtractionUtils; import com.android.launcher3.util.ManagedProfileHeuristic; import com.android.launcher3.util.NoLocaleSqliteContext; import com.android.launcher3.util.Thunk; @@ -257,7 +258,7 @@ public class LauncherProvider extends ContentProvider { } @Override - public Bundle call(String method, String arg, Bundle extras) { + public Bundle call(String method, final String arg, final Bundle extras) { if (Binder.getCallingUid() != Process.myUid()) { return null; } @@ -277,13 +278,19 @@ public class LauncherProvider extends ContentProvider { return result; } case LauncherSettings.Settings.METHOD_SET_BOOLEAN: { - boolean value = extras.getBoolean(LauncherSettings.Settings.EXTRA_VALUE); + final boolean value = extras.getBoolean(LauncherSettings.Settings.EXTRA_VALUE); Utilities.getPrefs(getContext()).edit().putBoolean(arg, value).apply(); - synchronized (LISTENER_LOCK) { - if (mListener != null) { - mListener.onSettingsChanged(arg, value); + new MainThreadExecutor().execute(new Runnable() { + @Override + public void run() { + synchronized (LISTENER_LOCK) { + if (mListener != null) { + mListener.onSettingsChanged(arg, value); + } + } + } - } + }); if (extras.getBoolean(LauncherSettings.Settings.NOTIFY_BACKUP)) { LauncherBackupAgentHelper.dataChanged(getContext()); } @@ -291,6 +298,29 @@ public class LauncherProvider extends ContentProvider { result.putBoolean(LauncherSettings.Settings.EXTRA_VALUE, value); return result; } + case LauncherSettings.Settings.METHOD_SET_EXTRACTED_COLORS_AND_WALLPAPER_ID: { + String extractedColors = extras.getString( + LauncherSettings.Settings.EXTRA_EXTRACTED_COLORS); + int wallpaperId = extras.getInt(LauncherSettings.Settings.EXTRA_WALLPAPER_ID); + Utilities.getPrefs(getContext()).edit() + .putString(ExtractionUtils.EXTRACTED_COLORS_PREFERENCE_KEY, extractedColors) + .putInt(ExtractionUtils.WALLPAPER_ID_PREFERENCE_KEY, wallpaperId) + .apply(); + new MainThreadExecutor().execute(new Runnable() { + @Override + public void run() { + synchronized (LISTENER_LOCK) { + if (mListener != null) { + mListener.onExtractedColorsChanged(); + } + } + + } + }); + Bundle result = new Bundle(); + result.putString(LauncherSettings.Settings.EXTRA_VALUE, extractedColors); + return result; + } case LauncherSettings.Settings.METHOD_CLEAR_EMPTY_DB_FLAG: { clearFlagEmptyDbCreated(); return null; diff --git a/src/com/android/launcher3/LauncherProviderChangeListener.java b/src/com/android/launcher3/LauncherProviderChangeListener.java index 1b78e9c18..2d2da6ec3 100644 --- a/src/com/android/launcher3/LauncherProviderChangeListener.java +++ b/src/com/android/launcher3/LauncherProviderChangeListener.java @@ -11,5 +11,7 @@ public interface LauncherProviderChangeListener { public void onSettingsChanged(String settings, boolean value); + public void onExtractedColorsChanged(); + public void onAppWidgetHostReset(); } diff --git a/src/com/android/launcher3/LauncherSettings.java b/src/com/android/launcher3/LauncherSettings.java index fb5306830..0c1628774 100644 --- a/src/com/android/launcher3/LauncherSettings.java +++ b/src/com/android/launcher3/LauncherSettings.java @@ -339,6 +339,11 @@ public class LauncherSettings { public static final String METHOD_LOAD_DEFAULT_FAVORITES = "load_default_favorites"; public static final String METHOD_MIGRATE_LAUNCHER2_SHORTCUTS = "migrate_l2_shortcuts"; + public static final String METHOD_SET_EXTRACTED_COLORS_AND_WALLPAPER_ID = + "set_extracted_colors_and_wallpaper_id_setting"; + public static final String EXTRA_EXTRACTED_COLORS = "extra_extractedColors"; + public static final String EXTRA_WALLPAPER_ID = "extra_wallpaperId"; + public static final String EXTRA_VALUE = "value"; public static final String EXTRA_DEFAULT_VALUE = "default_value"; // Extra for set_boolean method to also notify the backup manager of the change. diff --git a/src/com/android/launcher3/Utilities.java b/src/com/android/launcher3/Utilities.java index 3969d308b..ede427946 100644 --- a/src/com/android/launcher3/Utilities.java +++ b/src/com/android/launcher3/Utilities.java @@ -19,6 +19,7 @@ package com.android.launcher3; import android.annotation.TargetApi; import android.app.Activity; import android.app.SearchManager; +import android.app.WallpaperManager; import android.appwidget.AppWidgetManager; import android.appwidget.AppWidgetProviderInfo; import android.content.ActivityNotFoundException; @@ -63,10 +64,13 @@ import android.widget.Toast; import com.android.launcher3.compat.UserHandleCompat; import com.android.launcher3.config.FeatureFlags; import com.android.launcher3.config.ProviderConfig; +import com.android.launcher3.dynamicui.ColorExtractionService; import com.android.launcher3.util.IconNormalizer; +import com.android.wallpaperpicker.common.WallpaperManagerCompat; import java.io.ByteArrayOutputStream; import java.io.IOException; +import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.util.ArrayList; import java.util.Locale; diff --git a/src/com/android/launcher3/dynamicui/ColorExtractionService.java b/src/com/android/launcher3/dynamicui/ColorExtractionService.java new file mode 100644 index 000000000..95a62b957 --- /dev/null +++ b/src/com/android/launcher3/dynamicui/ColorExtractionService.java @@ -0,0 +1,63 @@ +/* + * Copyright (C) 2016 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.dynamicui; + +import android.app.IntentService; +import android.app.WallpaperManager; +import android.content.Intent; +import android.graphics.Bitmap; +import android.graphics.drawable.BitmapDrawable; +import android.os.Bundle; +import android.support.v7.graphics.Palette; + +import com.android.launcher3.LauncherProvider; +import com.android.launcher3.LauncherSettings; + +/** + * Extracts colors from the wallpaper, and saves results to {@link LauncherProvider}. + */ +public class ColorExtractionService extends IntentService { + + public ColorExtractionService() { + super("ColorExtractionService"); + } + + @Override + protected void onHandleIntent(Intent intent) { + WallpaperManager wallpaperManager = WallpaperManager.getInstance(this); + int wallpaperId = ExtractionUtils.getWallpaperId(wallpaperManager); + ExtractedColors extractedColors = new ExtractedColors(); + if (wallpaperManager.getWallpaperInfo() != null) { + // We can't extract colors from live wallpapers, so just use the default color always. + extractedColors.updatePalette(null); + } else { + Bitmap wallpaper = ((BitmapDrawable) wallpaperManager.getDrawable()).getBitmap(); + Palette palette = Palette.from(wallpaper).generate(); + extractedColors.updatePalette(palette); + } + + // Save the extracted colors and wallpaper id to LauncherProvider. + String colorsString = extractedColors.encodeAsString(); + Bundle extras = new Bundle(); + extras.putInt(LauncherSettings.Settings.EXTRA_WALLPAPER_ID, wallpaperId); + extras.putString(LauncherSettings.Settings.EXTRA_EXTRACTED_COLORS, colorsString); + getContentResolver().call( + LauncherSettings.Settings.CONTENT_URI, + LauncherSettings.Settings.METHOD_SET_EXTRACTED_COLORS_AND_WALLPAPER_ID, + null, extras); + } +} diff --git a/src/com/android/launcher3/dynamicui/ExtractedColors.java b/src/com/android/launcher3/dynamicui/ExtractedColors.java new file mode 100644 index 000000000..4d17ff764 --- /dev/null +++ b/src/com/android/launcher3/dynamicui/ExtractedColors.java @@ -0,0 +1,131 @@ +/* + * Copyright (C) 2016 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.dynamicui; + +import android.content.Context; +import android.graphics.Color; +import android.support.v7.graphics.Palette; +import android.util.Log; + +import com.android.launcher3.Utilities; + +/** + * Saves and loads colors extracted from the wallpaper, as well as the associated wallpaper id. + */ +public class ExtractedColors { + private static final String TAG = "ExtractedColors"; + + public static final int DEFAULT_LIGHT = Color.WHITE; + public static final int DEFAULT_DARK = Color.BLACK; + public static final int DEFAULT_COLOR = DEFAULT_LIGHT; + + // These color profile indices should NOT be changed, since they are used when saving and + // loading extracted colors. New colors should always be added at the end. + public static final int DEFAULT_INDEX = 0; + public static final int VIBRANT_INDEX = 1; + public static final int VIBRANT_DARK_INDEX = 2; + public static final int VIBRANT_LIGHT_INDEX = 3; + public static final int MUTED_INDEX = 4; + public static final int MUTED_DARK_INDEX = 5; + public static final int MUTED_LIGHT_INDEX = 6; + + public static final int NUM_COLOR_PROFILES = 7; + + private static final String COLOR_SEPARATOR = ","; + + private int[] mColors; + + public ExtractedColors() { + mColors = new int[NUM_COLOR_PROFILES]; + } + + public void setColorAtIndex(int index, int color) { + if (index >= 0 && index < mColors.length) { + mColors[index] = color; + } else { + Log.e(TAG, "Attempted to set a color at an invalid index " + index); + } + } + + /** + * Encodes {@link #mColors} as a comma-separated String. + */ + String encodeAsString() { + StringBuilder colorsStringBuilder = new StringBuilder(); + for (int color : mColors) { + colorsStringBuilder.append(color).append(COLOR_SEPARATOR); + } + return colorsStringBuilder.toString(); + } + + /** + * Decodes a comma-separated String into {@link #mColors}. + */ + void decodeFromString(String colorsString) { + String[] splitColorsString = colorsString.split(COLOR_SEPARATOR); + mColors = new int[splitColorsString.length]; + for (int i = 0; i < mColors.length; i++) { + mColors[i] = Integer.parseInt(splitColorsString[i]); + } + } + + /** + * Loads colors and wallpaper id from {@link Utilities#getPrefs(Context)}. + * These were saved there in {@link ColorExtractionService}. + */ + public void load(Context context) { + String encodedString = Utilities.getPrefs(context).getString( + ExtractionUtils.EXTRACTED_COLORS_PREFERENCE_KEY, DEFAULT_COLOR + ""); + + decodeFromString(encodedString); + } + + /** @param index must be one of the index values defined at the top of this class. */ + public int getColor(int index) { + if (index >= 0 && index < mColors.length) { + return mColors[index]; + } + return DEFAULT_COLOR; + } + + /** + * Updates colors based on the palette. + * If the palette is null, the default color is used in all cases. + */ + public void updatePalette(Palette palette) { + if (palette == null) { + for (int i = 0; i < NUM_COLOR_PROFILES; i++) { + setColorAtIndex(i, ExtractedColors.DEFAULT_COLOR); + } + } else { + setColorAtIndex(ExtractedColors.DEFAULT_INDEX, + ExtractedColors.DEFAULT_COLOR); + setColorAtIndex(ExtractedColors.VIBRANT_INDEX, + palette.getVibrantColor(ExtractedColors.DEFAULT_COLOR)); + setColorAtIndex(ExtractedColors.VIBRANT_DARK_INDEX, + palette.getDarkVibrantColor(ExtractedColors.DEFAULT_DARK)); + setColorAtIndex(ExtractedColors.VIBRANT_LIGHT_INDEX, + palette.getLightVibrantColor(ExtractedColors.DEFAULT_LIGHT)); + setColorAtIndex(ExtractedColors.MUTED_INDEX, + palette.getMutedColor(ExtractedColors.DEFAULT_COLOR)); + setColorAtIndex(ExtractedColors.MUTED_DARK_INDEX, + palette.getDarkMutedColor(ExtractedColors.DEFAULT_DARK)); + setColorAtIndex(ExtractedColors.MUTED_LIGHT_INDEX, + palette.getLightVibrantColor(ExtractedColors.DEFAULT_LIGHT)); + } + } +} diff --git a/src/com/android/launcher3/dynamicui/ExtractionUtils.java b/src/com/android/launcher3/dynamicui/ExtractionUtils.java new file mode 100644 index 000000000..a2ff60713 --- /dev/null +++ b/src/com/android/launcher3/dynamicui/ExtractionUtils.java @@ -0,0 +1,75 @@ +/* + * Copyright (C) 2016 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.dynamicui; + +import android.app.WallpaperManager; +import android.content.Context; +import android.content.Intent; +import android.content.SharedPreferences; + +import com.android.launcher3.Utilities; +import com.android.wallpaperpicker.common.WallpaperManagerCompat; + +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; + +/** + * Contains helper fields and methods related to extracting colors from the wallpaper. + */ +public class ExtractionUtils { + public static final String EXTRACTED_COLORS_PREFERENCE_KEY = "pref_extractedColors"; + public static final String WALLPAPER_ID_PREFERENCE_KEY = "pref_wallpaperId"; + + /** + * Extract colors in the :wallpaper-chooser process, if the wallpaper id has changed. + * When the new colors are saved in the LauncherProvider, + * Launcher will be notified in Launcher#onSettingsChanged(String, String). + */ + public static void startColorExtractionServiceIfNecessary(final Context context) { + // Run on a background thread, since the service is asynchronous anyway. + Utilities.THREAD_POOL_EXECUTOR.execute(new Runnable() { + @Override + public void run() { + if (hasWallpaperIdChanged(context)) { + context.startService(new Intent(context, ColorExtractionService.class)); + } + } + }); + } + + private static boolean hasWallpaperIdChanged(Context context) { + if (!Utilities.isNycOrAbove()) { + // TODO: update an id in sharedprefs in onWallpaperChanged broadcast, and read it here. + return false; + } + final SharedPreferences sharedPrefs = Utilities.getPrefs(context); + int wallpaperId = getWallpaperId(WallpaperManager.getInstance(context)); + int savedWallpaperId = sharedPrefs.getInt(ExtractionUtils.WALLPAPER_ID_PREFERENCE_KEY, -1); + return wallpaperId != savedWallpaperId; + } + + public static int getWallpaperId(WallpaperManager wallpaperManager) { + // TODO: use WallpaperManager#getWallpaperId(WallpaperManager.FLAG_SET_SYSTEM) directly. + try { + Method getWallpaperId = WallpaperManager.class.getMethod("getWallpaperId", int.class); + return (int) getWallpaperId.invoke(wallpaperManager, + WallpaperManagerCompat.FLAG_SET_SYSTEM); + } catch (InvocationTargetException | NoSuchMethodException | IllegalAccessException e) { + return -1; + } + } +} |