Removing dependency on wallpaper colors and using theme resources
Bug: 184676715 Test: Manual Change-Id: Ie9a9a784c4a8a8cd484bfd8ea463deedcd4deed6
This commit is contained in:
parent
f4bd91f0ab
commit
4ed0fb5074
|
@ -93,12 +93,6 @@
|
|||
</intent-filter>
|
||||
</receiver>
|
||||
|
||||
<service
|
||||
android:name="com.android.launcher3.uioverrides.dynamicui.WallpaperManagerCompatVL$ColorExtractionService"
|
||||
android:exported="false"
|
||||
android:process=":wallpaper_chooser"
|
||||
android:permission="android.permission.BIND_JOB_SERVICE" />
|
||||
|
||||
<service
|
||||
android:name="com.android.launcher3.notification.NotificationListener"
|
||||
android:label="@string/notification_dots_service_title"
|
||||
|
|
|
@ -97,9 +97,6 @@
|
|||
android:resource="@xml/overview_file_provider_paths"/>
|
||||
</provider>
|
||||
|
||||
<service android:name="com.android.launcher3.uioverrides.dynamicui.WallpaperManagerCompatVL$ColorExtractionService"
|
||||
tools:node="remove"/>
|
||||
|
||||
<activity android:name="com.android.launcher3.proxy.ProxyActivityStarter"
|
||||
android:theme="@android:style/Theme.Translucent.NoTitleBar.Fullscreen"
|
||||
android:launchMode="singleTask"
|
||||
|
|
|
@ -1,117 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 2018 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.android.launcher3.uioverrides;
|
||||
|
||||
import static android.app.WallpaperManager.FLAG_SYSTEM;
|
||||
|
||||
import android.annotation.TargetApi;
|
||||
import android.app.WallpaperColors;
|
||||
import android.app.WallpaperManager;
|
||||
import android.app.WallpaperManager.OnColorsChangedListener;
|
||||
import android.content.Context;
|
||||
import android.os.Build;
|
||||
import android.os.Handler;
|
||||
import android.os.Looper;
|
||||
|
||||
import com.android.launcher3.util.MainThreadInitializedObject;
|
||||
import com.android.systemui.shared.system.TonalCompat;
|
||||
import com.android.systemui.shared.system.TonalCompat.ExtractionInfo;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
@TargetApi(Build.VERSION_CODES.P)
|
||||
public class WallpaperColorInfo implements OnColorsChangedListener {
|
||||
|
||||
private static final int MAIN_COLOR_LIGHT = 0xffdadce0;
|
||||
private static final int MAIN_COLOR_DARK = 0xff202124;
|
||||
private static final int MAIN_COLOR_REGULAR = 0xff000000;
|
||||
|
||||
public static final MainThreadInitializedObject<WallpaperColorInfo> INSTANCE =
|
||||
new MainThreadInitializedObject<>(WallpaperColorInfo::new);
|
||||
|
||||
private final ArrayList<OnChangeListener> mListeners = new ArrayList<>();
|
||||
private final WallpaperManager mWallpaperManager;
|
||||
private final TonalCompat mTonalCompat;
|
||||
|
||||
private ExtractionInfo mExtractionInfo;
|
||||
|
||||
private OnChangeListener[] mTempListeners = new OnChangeListener[0];
|
||||
|
||||
private WallpaperColorInfo(Context context) {
|
||||
mWallpaperManager = context.getSystemService(WallpaperManager.class);
|
||||
mTonalCompat = new TonalCompat(context);
|
||||
|
||||
mWallpaperManager.addOnColorsChangedListener(this, new Handler(Looper.getMainLooper()));
|
||||
update(mWallpaperManager.getWallpaperColors(FLAG_SYSTEM));
|
||||
}
|
||||
|
||||
public int getMainColor() {
|
||||
return mExtractionInfo.mainColor;
|
||||
}
|
||||
|
||||
public int getSecondaryColor() {
|
||||
return mExtractionInfo.secondaryColor;
|
||||
}
|
||||
|
||||
public boolean isDark() {
|
||||
return mExtractionInfo.supportsDarkTheme;
|
||||
}
|
||||
|
||||
public boolean supportsDarkText() {
|
||||
return mExtractionInfo.supportsDarkText;
|
||||
}
|
||||
|
||||
public boolean isMainColorDark() {
|
||||
return mExtractionInfo.mainColor == MAIN_COLOR_DARK;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onColorsChanged(WallpaperColors colors, int which) {
|
||||
if ((which & FLAG_SYSTEM) != 0) {
|
||||
update(colors);
|
||||
notifyChange();
|
||||
}
|
||||
}
|
||||
|
||||
private void update(WallpaperColors wallpaperColors) {
|
||||
mExtractionInfo = mTonalCompat.extractDarkColors(wallpaperColors);
|
||||
}
|
||||
|
||||
public void addOnChangeListener(OnChangeListener listener) {
|
||||
mListeners.add(listener);
|
||||
}
|
||||
|
||||
public void removeOnChangeListener(OnChangeListener listener) {
|
||||
mListeners.remove(listener);
|
||||
}
|
||||
|
||||
private void notifyChange() {
|
||||
// Create a new array to avoid concurrent modification when the activity destroys itself.
|
||||
mTempListeners = mListeners.toArray(mTempListeners);
|
||||
for (int i = mTempListeners.length - 1; i >= 0; --i) {
|
||||
final OnChangeListener listener = mTempListeners[i];
|
||||
if (listener != null) {
|
||||
listener.onExtractedColorsChanged(this);
|
||||
mTempListeners[i] = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public interface OnChangeListener {
|
||||
void onExtractedColorsChanged(WallpaperColorInfo wallpaperColorInfo);
|
||||
}
|
||||
}
|
|
@ -16,11 +16,8 @@
|
|||
package com.android.quickstep.fallback;
|
||||
|
||||
import android.content.Context;
|
||||
import android.graphics.Rect;
|
||||
import android.util.AttributeSet;
|
||||
|
||||
import com.android.launcher3.R;
|
||||
import com.android.launcher3.util.Themes;
|
||||
import com.android.launcher3.util.TouchController;
|
||||
import com.android.launcher3.views.BaseDragLayer;
|
||||
import com.android.quickstep.RecentsActivity;
|
||||
|
@ -41,12 +38,4 @@ public class RecentsDragLayer extends BaseDragLayer<RecentsActivity> {
|
|||
new FallbackNavBarTouchController(mActivity),
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setInsets(Rect insets) {
|
||||
super.setInsets(insets);
|
||||
setBackground(insets.top == 0 || !mAllowSysuiScrims
|
||||
? null
|
||||
: Themes.getAttrDrawable(getContext(), R.attr.workspaceStatusBarScrim));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -140,7 +140,7 @@ public class StaggeredWorkspaceAnim {
|
|||
|
||||
addDepthAnimationForState(launcher, NORMAL, DURATION_MS);
|
||||
|
||||
mAnimators.play(launcher.getDragLayer().getSysUiScrim().createSysuiMultiplierAnim(0f, 1f)
|
||||
mAnimators.play(launcher.getRootView().getSysUiScrim().createSysuiMultiplierAnim(0f, 1f)
|
||||
.setDuration(DURATION_MS));
|
||||
mAnimators.addListener(new AnimatorListenerAdapter() {
|
||||
@Override
|
||||
|
|
|
@ -32,4 +32,7 @@
|
|||
<color name="text_color_primary_dark">@android:color/system_neutral1_50</color>
|
||||
<color name="text_color_secondary_dark">@android:color/system_neutral2_200</color>
|
||||
<color name="text_color_tertiary_dark">@android:color/system_neutral2_400</color>
|
||||
|
||||
<color name="wallpaper_popup_scrim">@android:color/system_neutral1_900</color>
|
||||
|
||||
</resources>
|
|
@ -19,7 +19,6 @@
|
|||
|
||||
<!-- Attributes used for launcher theme -->
|
||||
<attr name="allAppsScrimColor" format="color" />
|
||||
<attr name="allAppsInterimScrimAlpha" format="integer" />
|
||||
<attr name="allAppsNavBarScrimColor" format="color" />
|
||||
<attr name="allAppsTheme" format="reference" />
|
||||
<attr name="popupColorNeutral" format="color" />
|
||||
|
|
|
@ -57,4 +57,6 @@
|
|||
<color name="text_color_secondary_dark">#FFFFFFFF</color>
|
||||
<color name="text_color_tertiary_dark">#CCFFFFFF</color>
|
||||
|
||||
<color name="wallpaper_popup_scrim">?android:attr/colorAccent</color>
|
||||
|
||||
</resources>
|
||||
|
|
|
@ -216,9 +216,6 @@
|
|||
<item>@dimen/c2_d</item>
|
||||
</array>
|
||||
|
||||
<string-array name="live_wallpapers_remove_sysui_scrims">
|
||||
</string-array>
|
||||
|
||||
<string-array name="filtered_components" ></string-array>
|
||||
|
||||
<!-- Name of the class used to generate colors from the wallpaper colors. Must be implementing the LauncherAppWidgetHostView.ColorGenerator interface. -->
|
||||
|
|
|
@ -32,7 +32,6 @@
|
|||
<style name="LauncherTheme" parent="@style/BaseLauncherTheme">
|
||||
<item name="android:textColorSecondary">#DE000000</item>
|
||||
<item name="allAppsScrimColor">?android:attr/colorBackgroundFloating</item>
|
||||
<item name="allAppsInterimScrimAlpha">46</item>
|
||||
<item name="allAppsNavBarScrimColor">#66FFFFFF</item>
|
||||
<item name="allAppsTheme">@style/AllAppsTheme</item>
|
||||
<item name="popupColorNeutral">@color/popup_color_neutral_light</item>
|
||||
|
@ -77,7 +76,6 @@
|
|||
|
||||
<style name="LauncherTheme.DarkText" parent="@style/LauncherTheme">
|
||||
<item name="workspaceTextColor">@color/workspace_text_color_dark</item>
|
||||
<item name="allAppsInterimScrimAlpha">128</item>
|
||||
<item name="workspaceShadowColor">@android:color/transparent</item>
|
||||
<item name="workspaceAmbientShadowColor">@android:color/transparent</item>
|
||||
<item name="workspaceKeyShadowColor">@android:color/transparent</item>
|
||||
|
@ -97,7 +95,6 @@
|
|||
<item name="android:colorControlHighlight">#A0FFFFFF</item>
|
||||
<item name="android:colorPrimary">#FF212121</item>
|
||||
<item name="allAppsScrimColor">?android:attr/colorBackgroundFloating</item>
|
||||
<item name="allAppsInterimScrimAlpha">102</item>
|
||||
<item name="allAppsNavBarScrimColor">#80000000</item>
|
||||
<item name="allAppsTheme">@style/AllAppsTheme.Dark</item>
|
||||
<item name="popupColorNeutral">@color/popup_color_neutral_dark</item>
|
||||
|
@ -125,7 +122,6 @@
|
|||
|
||||
<style name="LauncherTheme.Dark.DarkText" parent="@style/LauncherTheme.Dark">
|
||||
<item name="android:colorControlHighlight">#75212121</item>
|
||||
<item name="allAppsInterimScrimAlpha">25</item>
|
||||
<item name="folderFillColor">#CDFFFFFF</item>
|
||||
<item name="folderTextColor">?attr/workspaceTextColor</item>
|
||||
<item name="workspaceTextColor">@color/workspace_text_color_dark</item>
|
||||
|
|
|
@ -18,8 +18,12 @@ package com.android.launcher3;
|
|||
|
||||
import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_APP_LAUNCH_TAP;
|
||||
import static com.android.launcher3.util.DisplayController.CHANGE_ROTATION;
|
||||
import static com.android.launcher3.util.Executors.MAIN_EXECUTOR;
|
||||
|
||||
import android.app.ActivityOptions;
|
||||
import android.app.WallpaperColors;
|
||||
import android.app.WallpaperManager;
|
||||
import android.app.WallpaperManager.OnColorsChangedListener;
|
||||
import android.content.ActivityNotFoundException;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
|
@ -54,7 +58,6 @@ import com.android.launcher3.logging.InstanceIdSequence;
|
|||
import com.android.launcher3.model.data.ItemInfo;
|
||||
import com.android.launcher3.model.data.WorkspaceItemInfo;
|
||||
import com.android.launcher3.touch.ItemClickHandler;
|
||||
import com.android.launcher3.uioverrides.WallpaperColorInfo;
|
||||
import com.android.launcher3.util.ActivityOptionsWrapper;
|
||||
import com.android.launcher3.util.DisplayController;
|
||||
import com.android.launcher3.util.DisplayController.DisplayInfoChangeListener;
|
||||
|
@ -68,8 +71,9 @@ import com.android.launcher3.util.WindowBounds;
|
|||
/**
|
||||
* Extension of BaseActivity allowing support for drag-n-drop
|
||||
*/
|
||||
@SuppressWarnings("NewApi")
|
||||
public abstract class BaseDraggingActivity extends BaseActivity
|
||||
implements WallpaperColorInfo.OnChangeListener, DisplayInfoChangeListener {
|
||||
implements OnColorsChangedListener, DisplayInfoChangeListener {
|
||||
|
||||
private static final String TAG = "BaseDraggingActivity";
|
||||
|
||||
|
@ -89,13 +93,15 @@ public abstract class BaseDraggingActivity extends BaseActivity
|
|||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
|
||||
|
||||
mIsSafeModeEnabled = TraceHelper.allowIpcs("isSafeMode",
|
||||
() -> getPackageManager().isSafeMode());
|
||||
DisplayController.INSTANCE.get(this).addChangeListener(this);
|
||||
|
||||
// Update theme
|
||||
WallpaperColorInfo.INSTANCE.get(this).addOnChangeListener(this);
|
||||
if (Utilities.ATLEAST_P) {
|
||||
getSystemService(WallpaperManager.class)
|
||||
.addOnColorsChangedListener(this, MAIN_EXECUTOR.getHandler());
|
||||
}
|
||||
int themeRes = Themes.getActivityThemeRes(this);
|
||||
if (themeRes != mThemeRes) {
|
||||
mThemeRes = themeRes;
|
||||
|
@ -114,7 +120,7 @@ public abstract class BaseDraggingActivity extends BaseActivity
|
|||
}
|
||||
|
||||
@Override
|
||||
public void onExtractedColorsChanged(WallpaperColorInfo wallpaperColorInfo) {
|
||||
public void onColorsChanged(WallpaperColors wallpaperColors, int which) {
|
||||
updateTheme();
|
||||
}
|
||||
|
||||
|
@ -278,7 +284,9 @@ public abstract class BaseDraggingActivity extends BaseActivity
|
|||
@Override
|
||||
protected void onDestroy() {
|
||||
super.onDestroy();
|
||||
WallpaperColorInfo.INSTANCE.get(this).removeOnChangeListener(this);
|
||||
if (Utilities.ATLEAST_P) {
|
||||
getSystemService(WallpaperManager.class).removeOnColorsChangedListener(this);
|
||||
}
|
||||
DisplayController.INSTANCE.get(this).removeChangeListener(this);
|
||||
}
|
||||
|
||||
|
|
|
@ -33,11 +33,12 @@ public class LauncherRootView extends InsettableFrameLayout {
|
|||
@ViewDebug.ExportedProperty(category = "launcher")
|
||||
private boolean mForceHideBackArrow;
|
||||
|
||||
private SysUiScrim mSysUiScrim;
|
||||
private final SysUiScrim mSysUiScrim;
|
||||
|
||||
public LauncherRootView(Context context, AttributeSet attrs) {
|
||||
super(context, attrs);
|
||||
mActivity = StatefulActivity.fromContext(context);
|
||||
mSysUiScrim = new SysUiScrim(this);
|
||||
}
|
||||
|
||||
private void handleSystemWindowInsets(Rect insets) {
|
||||
|
@ -72,6 +73,7 @@ public class LauncherRootView extends InsettableFrameLayout {
|
|||
// modifying child layout params.
|
||||
if (!insets.equals(mInsets)) {
|
||||
super.setInsets(insets);
|
||||
mSysUiScrim.onInsetsChanged(insets);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -100,15 +102,9 @@ public class LauncherRootView extends InsettableFrameLayout {
|
|||
}
|
||||
}
|
||||
|
||||
public void setSysUiScrim(SysUiScrim scrim) {
|
||||
mSysUiScrim = scrim;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void dispatchDraw(Canvas canvas) {
|
||||
if (mSysUiScrim != null) {
|
||||
mSysUiScrim.draw(canvas);
|
||||
}
|
||||
mSysUiScrim.draw(canvas);
|
||||
super.dispatchDraw(canvas);
|
||||
}
|
||||
|
||||
|
@ -117,6 +113,7 @@ public class LauncherRootView extends InsettableFrameLayout {
|
|||
super.onLayout(changed, l, t, r, b);
|
||||
SYSTEM_GESTURE_EXCLUSION_RECT.get(0).set(l, t, r, b);
|
||||
setDisallowBackGesture(mDisallowBackGesture);
|
||||
mSysUiScrim.setSize(r - l, b - t);
|
||||
}
|
||||
|
||||
@TargetApi(Build.VERSION_CODES.Q)
|
||||
|
@ -136,6 +133,10 @@ public class LauncherRootView extends InsettableFrameLayout {
|
|||
: Collections.emptyList());
|
||||
}
|
||||
|
||||
public SysUiScrim getSysUiScrim() {
|
||||
return mSysUiScrim;
|
||||
}
|
||||
|
||||
public interface WindowStateListener {
|
||||
|
||||
void onWindowFocusChanged(boolean hasFocus);
|
||||
|
|
|
@ -2066,9 +2066,6 @@ public class Workspace extends PagedView<WorkspacePageIndicator>
|
|||
if (mDragOverlappingLayout != null) {
|
||||
mDragOverlappingLayout.setIsDragOverlapping(true);
|
||||
}
|
||||
// Invalidating the scrim will also force this CellLayout
|
||||
// to be invalidated so that it is highlighted if necessary.
|
||||
mLauncher.getDragLayer().getWorkspaceDragScrim().invalidate();
|
||||
}
|
||||
|
||||
public CellLayout getCurrentDragOverlappingLayout() {
|
||||
|
|
|
@ -162,7 +162,7 @@ public class WorkspaceStateTransitionAnimation {
|
|||
propertySetter.setFloat(workspaceDragScrim, SCRIM_PROGRESS,
|
||||
state.getWorkspaceBackgroundAlpha(mLauncher), LINEAR);
|
||||
|
||||
SysUiScrim sysUiScrim = mLauncher.getDragLayer().getSysUiScrim();
|
||||
SysUiScrim sysUiScrim = mLauncher.getRootView().getSysUiScrim();
|
||||
propertySetter.setFloat(sysUiScrim, SYSUI_PROGRESS,
|
||||
state.hasFlag(FLAG_HAS_SYS_UI_SCRIM) ? 1 : 0, LINEAR);
|
||||
|
||||
|
|
|
@ -41,13 +41,11 @@ import com.android.launcher3.AbstractFloatingView;
|
|||
import com.android.launcher3.CellLayout;
|
||||
import com.android.launcher3.DropTargetBar;
|
||||
import com.android.launcher3.Launcher;
|
||||
import com.android.launcher3.LauncherRootView;
|
||||
import com.android.launcher3.R;
|
||||
import com.android.launcher3.ShortcutAndWidgetContainer;
|
||||
import com.android.launcher3.Workspace;
|
||||
import com.android.launcher3.folder.Folder;
|
||||
import com.android.launcher3.graphics.Scrim;
|
||||
import com.android.launcher3.graphics.SysUiScrim;
|
||||
import com.android.launcher3.keyboard.ViewGroupFocusHelper;
|
||||
import com.android.launcher3.util.Thunk;
|
||||
import com.android.launcher3.views.BaseDragLayer;
|
||||
|
@ -84,8 +82,6 @@ public class DragLayer extends BaseDragLayer<Launcher> {
|
|||
// Related to adjacent page hints
|
||||
private final ViewGroupFocusHelper mFocusIndicatorHelper;
|
||||
private Scrim mWorkspaceDragScrim;
|
||||
private SysUiScrim mSysUiScrim;
|
||||
private LauncherRootView mRootView;
|
||||
|
||||
/**
|
||||
* Used to create a new DragLayer from XML.
|
||||
|
@ -107,12 +103,6 @@ public class DragLayer extends BaseDragLayer<Launcher> {
|
|||
mDragController = dragController;
|
||||
recreateControllers();
|
||||
mWorkspaceDragScrim = new Scrim(this);
|
||||
|
||||
// We delegate drawing of the workspace scrim to LauncherRootView (one level up), so as
|
||||
// to avoid artifacts when translating the entire drag layer in the -1 transition.
|
||||
mRootView = (LauncherRootView) getParent();
|
||||
mSysUiScrim = new SysUiScrim(mRootView);
|
||||
mRootView.setSysUiScrim(mSysUiScrim);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -526,23 +516,7 @@ public class DragLayer extends BaseDragLayer<Launcher> {
|
|||
super.dispatchDraw(canvas);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
|
||||
super.onSizeChanged(w, h, oldw, oldh);
|
||||
mSysUiScrim.setSize(w, h);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setInsets(Rect insets) {
|
||||
super.setInsets(insets);
|
||||
mSysUiScrim.onInsetsChanged(insets, mAllowSysuiScrims);
|
||||
}
|
||||
|
||||
public Scrim getWorkspaceDragScrim() {
|
||||
return mWorkspaceDragScrim;
|
||||
}
|
||||
|
||||
public SysUiScrim getSysUiScrim() {
|
||||
return mSysUiScrim;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -22,14 +22,12 @@ import android.graphics.Canvas;
|
|||
import android.util.FloatProperty;
|
||||
import android.view.View;
|
||||
|
||||
import com.android.launcher3.Launcher;
|
||||
import com.android.launcher3.uioverrides.WallpaperColorInfo;
|
||||
import com.android.launcher3.R;
|
||||
|
||||
/**
|
||||
* Contains general scrim properties such as wallpaper-extracted color that subclasses can use.
|
||||
*/
|
||||
public class Scrim implements View.OnAttachStateChangeListener,
|
||||
WallpaperColorInfo.OnChangeListener {
|
||||
public class Scrim {
|
||||
|
||||
public static final FloatProperty<Scrim> SCRIM_PROGRESS =
|
||||
new FloatProperty<Scrim>("scrimProgress") {
|
||||
|
@ -44,8 +42,6 @@ public class Scrim implements View.OnAttachStateChangeListener,
|
|||
}
|
||||
};
|
||||
|
||||
protected final Launcher mLauncher;
|
||||
protected final WallpaperColorInfo mWallpaperColorInfo;
|
||||
protected final View mRoot;
|
||||
|
||||
protected float mScrimProgress;
|
||||
|
@ -54,48 +50,18 @@ public class Scrim implements View.OnAttachStateChangeListener,
|
|||
|
||||
public Scrim(View view) {
|
||||
mRoot = view;
|
||||
mLauncher = Launcher.getLauncher(view.getContext());
|
||||
mWallpaperColorInfo = WallpaperColorInfo.INSTANCE.get(mLauncher);
|
||||
|
||||
view.addOnAttachStateChangeListener(this);
|
||||
mScrimColor = mRoot.getContext().getColor(R.color.wallpaper_popup_scrim);
|
||||
}
|
||||
|
||||
public void draw(Canvas canvas) {
|
||||
canvas.drawColor(setColorAlphaBound(mScrimColor, getScrimAlpha()));
|
||||
}
|
||||
|
||||
protected int getScrimAlpha() {
|
||||
return mScrimAlpha;
|
||||
canvas.drawColor(setColorAlphaBound(mScrimColor, mScrimAlpha));
|
||||
}
|
||||
|
||||
private void setScrimProgress(float progress) {
|
||||
if (mScrimProgress != progress) {
|
||||
mScrimProgress = progress;
|
||||
mScrimAlpha = Math.round(255 * mScrimProgress);
|
||||
invalidate();
|
||||
mRoot.invalidate();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onViewAttachedToWindow(View view) {
|
||||
mWallpaperColorInfo.addOnChangeListener(this);
|
||||
onExtractedColorsChanged(mWallpaperColorInfo);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onViewDetachedFromWindow(View view) {
|
||||
mWallpaperColorInfo.removeOnChangeListener(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onExtractedColorsChanged(WallpaperColorInfo wallpaperColorInfo) {
|
||||
mScrimColor = wallpaperColorInfo.getMainColor();
|
||||
if (mScrimAlpha > 0) {
|
||||
invalidate();
|
||||
}
|
||||
}
|
||||
|
||||
public void invalidate() {
|
||||
mRoot.invalidate();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -41,18 +41,16 @@ import android.util.FloatProperty;
|
|||
import android.view.View;
|
||||
import android.view.WindowInsets;
|
||||
|
||||
import androidx.core.graphics.ColorUtils;
|
||||
|
||||
import com.android.launcher3.BaseDraggingActivity;
|
||||
import com.android.launcher3.R;
|
||||
import com.android.launcher3.ResourceUtils;
|
||||
import com.android.launcher3.Utilities;
|
||||
import com.android.launcher3.uioverrides.WallpaperColorInfo;
|
||||
import com.android.launcher3.util.Themes;
|
||||
|
||||
/**
|
||||
* View scrim which draws behind hotseat and workspace
|
||||
*/
|
||||
public class SysUiScrim extends Scrim {
|
||||
public class SysUiScrim implements View.OnAttachStateChangeListener {
|
||||
|
||||
public static final FloatProperty<SysUiScrim> SYSUI_PROGRESS =
|
||||
new FloatProperty<SysUiScrim>("sysUiProgress") {
|
||||
|
@ -83,7 +81,6 @@ public class SysUiScrim extends Scrim {
|
|||
|
||||
/**
|
||||
* Receiver used to get a signal that the user unlocked their device.
|
||||
* @see KEYGUARD_ANIMATION For proper signal.
|
||||
*/
|
||||
private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
|
||||
@Override
|
||||
|
@ -99,7 +96,6 @@ public class SysUiScrim extends Scrim {
|
|||
}
|
||||
};
|
||||
|
||||
private static final int DARK_SCRIM_COLOR = 0x55000000;
|
||||
private static final int MAX_HOTSEAT_SCRIM_ALPHA = 100;
|
||||
private static final int ALPHA_MASK_HEIGHT_DP = 500;
|
||||
private static final int ALPHA_MASK_BITMAP_DP = 200;
|
||||
|
@ -112,6 +108,8 @@ public class SysUiScrim extends Scrim {
|
|||
private final Bitmap mBottomMask;
|
||||
private final int mMaskHeight;
|
||||
|
||||
private final View mRoot;
|
||||
private final BaseDraggingActivity mActivity;
|
||||
private final Drawable mTopScrim;
|
||||
|
||||
private float mSysUiProgress = 1;
|
||||
|
@ -121,14 +119,15 @@ public class SysUiScrim extends Scrim {
|
|||
private float mSysUiAnimMultiplier = 1;
|
||||
|
||||
public SysUiScrim(View view) {
|
||||
super(view);
|
||||
mRoot = view;
|
||||
mActivity = BaseDraggingActivity.fromContext(view.getContext());
|
||||
mMaskHeight = ResourceUtils.pxFromDp(ALPHA_MASK_BITMAP_DP,
|
||||
view.getResources().getDisplayMetrics());
|
||||
mTopScrim = Themes.getAttrDrawable(view.getContext(), R.attr.workspaceStatusBarScrim);
|
||||
mBottomMask = mTopScrim == null ? null : createDitheredAlphaMask();
|
||||
mHideSysUiScrim = mTopScrim == null;
|
||||
|
||||
onExtractedColorsChanged(mWallpaperColorInfo);
|
||||
view.addOnAttachStateChangeListener(this);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -147,7 +146,7 @@ public class SysUiScrim extends Scrim {
|
|||
|
||||
ObjectAnimator oa = createSysuiMultiplierAnim(1);
|
||||
oa.setDuration(600);
|
||||
oa.setStartDelay(mLauncher.getWindow().getTransitionBackgroundFadeDuration());
|
||||
oa.setStartDelay(mActivity.getWindow().getTransitionBackgroundFadeDuration());
|
||||
oa.start();
|
||||
mAnimateScrimOnNextDraw = false;
|
||||
}
|
||||
|
@ -173,20 +172,17 @@ public class SysUiScrim extends Scrim {
|
|||
/**
|
||||
* Determines whether to draw the top and/or bottom scrim based on new insets.
|
||||
*/
|
||||
public void onInsetsChanged(Rect insets, boolean allowSysuiScrims) {
|
||||
mDrawTopScrim = allowSysuiScrims
|
||||
&& mTopScrim != null
|
||||
&& insets.top > 0;
|
||||
mDrawBottomScrim = allowSysuiScrims
|
||||
&& mBottomMask != null
|
||||
&& !mLauncher.getDeviceProfile().isVerticalBarLayout()
|
||||
public void onInsetsChanged(Rect insets) {
|
||||
mDrawTopScrim = mTopScrim != null && insets.top > 0;
|
||||
mDrawBottomScrim = mBottomMask != null
|
||||
&& !mActivity.getDeviceProfile().isVerticalBarLayout()
|
||||
&& hasBottomNavButtons();
|
||||
}
|
||||
|
||||
private boolean hasBottomNavButtons() {
|
||||
if (Utilities.ATLEAST_Q && mLauncher.getRootView() != null
|
||||
&& mLauncher.getRootView().getRootWindowInsets() != null) {
|
||||
WindowInsets windowInsets = mLauncher.getRootView().getRootWindowInsets();
|
||||
if (Utilities.ATLEAST_Q && mActivity.getRootView() != null
|
||||
&& mActivity.getRootView().getRootWindowInsets() != null) {
|
||||
WindowInsets windowInsets = mActivity.getRootView().getRootWindowInsets();
|
||||
return windowInsets.getTappableElementInsets().bottom > 0;
|
||||
}
|
||||
return true;
|
||||
|
@ -194,8 +190,6 @@ public class SysUiScrim extends Scrim {
|
|||
|
||||
@Override
|
||||
public void onViewAttachedToWindow(View view) {
|
||||
super.onViewAttachedToWindow(view);
|
||||
|
||||
if (!KEYGUARD_ANIMATION.get() && mTopScrim != null) {
|
||||
IntentFilter filter = new IntentFilter(ACTION_SCREEN_OFF);
|
||||
filter.addAction(ACTION_USER_PRESENT); // When the device wakes up + keyguard is gone
|
||||
|
@ -205,22 +199,11 @@ public class SysUiScrim extends Scrim {
|
|||
|
||||
@Override
|
||||
public void onViewDetachedFromWindow(View view) {
|
||||
super.onViewDetachedFromWindow(view);
|
||||
if (!KEYGUARD_ANIMATION.get() && mTopScrim != null) {
|
||||
mRoot.getContext().unregisterReceiver(mReceiver);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onExtractedColorsChanged(WallpaperColorInfo wallpaperColorInfo) {
|
||||
// for super light wallpaper it needs to be darken for contrast to workspace
|
||||
// for dark wallpapers the text is white so darkening works as well
|
||||
mBottomMaskPaint.setColor(ColorUtils.compositeColors(DARK_SCRIM_COLOR,
|
||||
wallpaperColorInfo.getMainColor()));
|
||||
reapplySysUiAlpha();
|
||||
super.onExtractedColorsChanged(wallpaperColorInfo);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the width and height of the view being scrimmed
|
||||
* @param w
|
||||
|
@ -243,7 +226,7 @@ public class SysUiScrim extends Scrim {
|
|||
private void reapplySysUiAlpha() {
|
||||
reapplySysUiAlphaNoInvalidate();
|
||||
if (!mHideSysUiScrim) {
|
||||
invalidate();
|
||||
mRoot.invalidate();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -256,7 +239,7 @@ public class SysUiScrim extends Scrim {
|
|||
}
|
||||
|
||||
private Bitmap createDitheredAlphaMask() {
|
||||
DisplayMetrics dm = mLauncher.getResources().getDisplayMetrics();
|
||||
DisplayMetrics dm = mActivity.getResources().getDisplayMetrics();
|
||||
int width = ResourceUtils.pxFromDp(ALPHA_MASK_WIDTH_DP, dm);
|
||||
int gradientHeight = ResourceUtils.pxFromDp(ALPHA_MASK_HEIGHT_DP, dm);
|
||||
Bitmap dst = Bitmap.createBitmap(width, mMaskHeight, Bitmap.Config.ALPHA_8);
|
||||
|
|
|
@ -24,7 +24,7 @@ import com.android.launcher3.Insettable;
|
|||
import com.android.launcher3.Launcher;
|
||||
import com.android.launcher3.R;
|
||||
import com.android.launcher3.Utilities;
|
||||
import com.android.launcher3.uioverrides.WallpaperColorInfo;
|
||||
import com.android.launcher3.util.Themes;
|
||||
|
||||
/**
|
||||
* A PageIndicator that briefly shows a fraction of a line when moving between pages
|
||||
|
@ -123,7 +123,7 @@ public class WorkspacePageIndicator extends View implements Insettable, PageIndi
|
|||
mLauncher = Launcher.getLauncher(context);
|
||||
mLineHeight = res.getDimensionPixelSize(R.dimen.workspace_page_indicator_line_height);
|
||||
|
||||
boolean darkText = WallpaperColorInfo.INSTANCE.get(context).supportsDarkText();
|
||||
boolean darkText = Themes.getAttrBoolean(mLauncher, R.attr.isWorkspaceDarkText);
|
||||
mActiveAlpha = darkText ? BLACK_ALPHA : WHITE_ALPHA;
|
||||
mLinePaint.setColor(darkText ? Color.BLACK : Color.WHITE);
|
||||
}
|
||||
|
|
|
@ -89,7 +89,7 @@ public class SpringLoadedState extends LauncherState {
|
|||
|
||||
@Override
|
||||
public float getWorkspaceBackgroundAlpha(Launcher launcher) {
|
||||
return 0.3f;
|
||||
return 0.2f;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -352,7 +352,7 @@ public abstract class AbstractStateChangeTouchController
|
|||
// case the user started interacting with it before the animation finished.
|
||||
mLauncher.getStateManager().goToState(targetState, false /* animated */);
|
||||
}
|
||||
mLauncher.getDragLayer().getSysUiScrim().createSysuiMultiplierAnim(
|
||||
mLauncher.getRootView().getSysUiScrim().createSysuiMultiplierAnim(
|
||||
1f).setDuration(0).start();
|
||||
}
|
||||
|
||||
|
|
|
@ -16,6 +16,10 @@
|
|||
|
||||
package com.android.launcher3.util;
|
||||
|
||||
import static android.app.WallpaperColors.HINT_SUPPORTS_DARK_TEXT;
|
||||
import static android.app.WallpaperColors.HINT_SUPPORTS_DARK_THEME;
|
||||
|
||||
import android.app.WallpaperManager;
|
||||
import android.content.Context;
|
||||
import android.content.res.Configuration;
|
||||
import android.content.res.TypedArray;
|
||||
|
@ -29,35 +33,40 @@ import android.util.TypedValue;
|
|||
import com.android.launcher3.R;
|
||||
import com.android.launcher3.Utilities;
|
||||
import com.android.launcher3.icons.GraphicsUtils;
|
||||
import com.android.launcher3.uioverrides.WallpaperColorInfo;
|
||||
|
||||
/**
|
||||
* Various utility methods associated with theming.
|
||||
*/
|
||||
@SuppressWarnings("NewApi")
|
||||
public class Themes {
|
||||
|
||||
public static int getActivityThemeRes(Context context) {
|
||||
WallpaperColorInfo wallpaperColorInfo = WallpaperColorInfo.INSTANCE.get(context);
|
||||
boolean darkTheme;
|
||||
if (Utilities.ATLEAST_Q) {
|
||||
Configuration configuration = context.getResources().getConfiguration();
|
||||
int nightMode = configuration.uiMode & Configuration.UI_MODE_NIGHT_MASK;
|
||||
darkTheme = nightMode == Configuration.UI_MODE_NIGHT_YES;
|
||||
} else {
|
||||
darkTheme = wallpaperColorInfo.isDark();
|
||||
}
|
||||
int colorHints = Utilities.ATLEAST_P ? context.getSystemService(WallpaperManager.class)
|
||||
.getWallpaperColors(WallpaperManager.FLAG_SYSTEM).getColorHints()
|
||||
: 0;
|
||||
return getActivityThemeRes(context, colorHints);
|
||||
}
|
||||
|
||||
public static int getActivityThemeRes(Context context, int wallpaperColorHints) {
|
||||
Configuration configuration = context.getResources().getConfiguration();
|
||||
int nightMode = configuration.uiMode & Configuration.UI_MODE_NIGHT_MASK;
|
||||
boolean darkTheme = nightMode == Configuration.UI_MODE_NIGHT_YES;
|
||||
|
||||
boolean supportsDarkText = Utilities.ATLEAST_S
|
||||
&& (wallpaperColorHints & HINT_SUPPORTS_DARK_TEXT) != 0;
|
||||
boolean isMainColorDark = Utilities.ATLEAST_S
|
||||
&& (wallpaperColorHints & HINT_SUPPORTS_DARK_THEME) != 0;
|
||||
|
||||
if (darkTheme) {
|
||||
return wallpaperColorInfo.supportsDarkText() ?
|
||||
R.style.AppTheme_Dark_DarkText : wallpaperColorInfo.isMainColorDark() ?
|
||||
R.style.AppTheme_Dark_DarkMainColor : R.style.AppTheme_Dark;
|
||||
return supportsDarkText ? R.style.AppTheme_Dark_DarkText
|
||||
: isMainColorDark ? R.style.AppTheme_Dark_DarkMainColor : R.style.AppTheme_Dark;
|
||||
} else {
|
||||
return wallpaperColorInfo.supportsDarkText() ?
|
||||
R.style.AppTheme_DarkText : wallpaperColorInfo.isMainColorDark() ?
|
||||
R.style.AppTheme_DarkMainColor : R.style.AppTheme;
|
||||
return supportsDarkText ? R.style.AppTheme_DarkText
|
||||
: isMainColorDark ? R.style.AppTheme_DarkMainColor : R.style.AppTheme;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static String getDefaultBodyFont(Context context) {
|
||||
TypedArray ta = context.obtainStyledAttributes(android.R.style.TextAppearance_DeviceDefault,
|
||||
new int[]{android.R.attr.fontFamily});
|
||||
|
|
|
@ -23,11 +23,8 @@ import static android.view.MotionEvent.ACTION_UP;
|
|||
import static com.android.launcher3.util.DisplayController.getSingleFrameMs;
|
||||
|
||||
import android.annotation.TargetApi;
|
||||
import android.app.WallpaperInfo;
|
||||
import android.app.WallpaperManager;
|
||||
import android.content.ComponentName;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.graphics.Insets;
|
||||
import android.graphics.Rect;
|
||||
import android.graphics.RectF;
|
||||
|
@ -42,15 +39,11 @@ import android.view.WindowInsets;
|
|||
import android.view.accessibility.AccessibilityEvent;
|
||||
import android.widget.FrameLayout;
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
import com.android.launcher3.AbstractFloatingView;
|
||||
import com.android.launcher3.InsettableFrameLayout;
|
||||
import com.android.launcher3.R;
|
||||
import com.android.launcher3.Utilities;
|
||||
import com.android.launcher3.util.MultiValueAlpha;
|
||||
import com.android.launcher3.util.MultiValueAlpha.AlphaProperty;
|
||||
import com.android.launcher3.util.SimpleBroadcastReceiver;
|
||||
import com.android.launcher3.util.TouchController;
|
||||
|
||||
import java.io.PrintWriter;
|
||||
|
@ -117,9 +110,6 @@ public abstract class BaseDragLayer<T extends Context & ActivityContext>
|
|||
protected final T mActivity;
|
||||
private final MultiValueAlpha mMultiValueAlpha;
|
||||
private final WallpaperManager mWallpaperManager;
|
||||
private final SimpleBroadcastReceiver mWallpaperChangeReceiver =
|
||||
new SimpleBroadcastReceiver(this::onWallpaperChanged);
|
||||
private final String[] mWallpapersWithoutSysuiScrims;
|
||||
|
||||
// All the touch controllers for the view
|
||||
protected TouchController[] mControllers;
|
||||
|
@ -130,15 +120,11 @@ public abstract class BaseDragLayer<T extends Context & ActivityContext>
|
|||
|
||||
private TouchCompleteListener mTouchCompleteListener;
|
||||
|
||||
protected boolean mAllowSysuiScrims = true;
|
||||
|
||||
public BaseDragLayer(Context context, AttributeSet attrs, int alphaChannelCount) {
|
||||
super(context, attrs);
|
||||
mActivity = (T) ActivityContext.lookupContext(context);
|
||||
mMultiValueAlpha = new MultiValueAlpha(this, alphaChannelCount);
|
||||
mWallpaperManager = context.getSystemService(WallpaperManager.class);
|
||||
mWallpapersWithoutSysuiScrims = getResources().getStringArray(
|
||||
R.array.live_wallpapers_remove_sysui_scrims);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -562,46 +548,4 @@ public abstract class BaseDragLayer<T extends Context & ActivityContext>
|
|||
}
|
||||
return super.dispatchApplyWindowInsets(insets);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onAttachedToWindow() {
|
||||
super.onAttachedToWindow();
|
||||
mWallpaperChangeReceiver.register(mActivity, Intent.ACTION_WALLPAPER_CHANGED);
|
||||
onWallpaperChanged(null);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onDetachedFromWindow() {
|
||||
super.onDetachedFromWindow();
|
||||
mActivity.unregisterReceiver(mWallpaperChangeReceiver);
|
||||
}
|
||||
|
||||
private void onWallpaperChanged(Intent unusedBroadcastIntent) {
|
||||
WallpaperInfo newWallpaperInfo = mWallpaperManager.getWallpaperInfo();
|
||||
boolean oldAllowSysuiScrims = mAllowSysuiScrims;
|
||||
mAllowSysuiScrims = computeAllowSysuiScrims(newWallpaperInfo);
|
||||
if (mAllowSysuiScrims != oldAllowSysuiScrims) {
|
||||
// Reapply insets so scrim can be removed or re-added if necessary.
|
||||
setInsets(mInsets);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines whether we can scrim the status bar and nav bar for the given wallpaper by
|
||||
* checking against a list of live wallpapers that we don't show the scrims on.
|
||||
*/
|
||||
private boolean computeAllowSysuiScrims(@Nullable WallpaperInfo newWallpaperInfo) {
|
||||
if (newWallpaperInfo == null) {
|
||||
// Static wallpapers need scrim unless determined otherwise by wallpaperColors.
|
||||
return true;
|
||||
}
|
||||
ComponentName newWallpaper = newWallpaperInfo.getComponent();
|
||||
for (String wallpaperWithoutScrim : mWallpapersWithoutSysuiScrims) {
|
||||
if (newWallpaper.equals(ComponentName.unflattenFromString(wallpaperWithoutScrim))) {
|
||||
// New wallpaper does not need a scrim.
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -35,7 +35,6 @@ import com.android.launcher3.popup.PopupDataProvider;
|
|||
import com.android.launcher3.testing.TestLogging;
|
||||
import com.android.launcher3.testing.TestProtocol;
|
||||
import com.android.launcher3.touch.ItemLongClickListener;
|
||||
import com.android.launcher3.uioverrides.WallpaperColorInfo;
|
||||
import com.android.launcher3.util.SystemUiController;
|
||||
import com.android.launcher3.util.Themes;
|
||||
import com.android.launcher3.views.AbstractSlideInView;
|
||||
|
@ -56,9 +55,8 @@ public abstract class BaseWidgetSheet extends AbstractSlideInView
|
|||
}
|
||||
|
||||
protected int getScrimColor(Context context) {
|
||||
WallpaperColorInfo colors = WallpaperColorInfo.INSTANCE.get(context);
|
||||
int alpha = context.getResources().getInteger(R.integer.extracted_color_gradient_alpha);
|
||||
return setColorAlphaBound(colors.getSecondaryColor(), alpha);
|
||||
return setColorAlphaBound(context.getColor(R.color.wallpaper_popup_scrim), alpha);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -1,128 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 2018 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.android.launcher3.uioverrides;
|
||||
|
||||
import static android.app.WallpaperManager.FLAG_SYSTEM;
|
||||
|
||||
import android.content.Context;
|
||||
import android.graphics.Color;
|
||||
import android.util.Pair;
|
||||
|
||||
import com.android.launcher3.uioverrides.dynamicui.ColorExtractionAlgorithm;
|
||||
import com.android.launcher3.uioverrides.dynamicui.WallpaperColorsCompat;
|
||||
import com.android.launcher3.uioverrides.dynamicui.WallpaperManagerCompat;
|
||||
import com.android.launcher3.util.MainThreadInitializedObject;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
public class WallpaperColorInfo implements WallpaperManagerCompat.OnColorsChangedListenerCompat {
|
||||
|
||||
private static final int MAIN_COLOR_LIGHT = 0xffdadce0;
|
||||
private static final int MAIN_COLOR_DARK = 0xff202124;
|
||||
private static final int MAIN_COLOR_REGULAR = 0xff000000;
|
||||
|
||||
private static final int FALLBACK_COLOR = Color.WHITE;
|
||||
|
||||
public static final MainThreadInitializedObject<WallpaperColorInfo> INSTANCE =
|
||||
new MainThreadInitializedObject<>(WallpaperColorInfo::new);
|
||||
|
||||
private final ArrayList<OnChangeListener> mListeners = new ArrayList<>();
|
||||
private final WallpaperManagerCompat mWallpaperManager;
|
||||
private final ColorExtractionAlgorithm mExtractionType;
|
||||
private int mMainColor;
|
||||
private int mSecondaryColor;
|
||||
private boolean mIsDark;
|
||||
private boolean mSupportsDarkText;
|
||||
|
||||
private OnChangeListener[] mTempListeners;
|
||||
|
||||
private WallpaperColorInfo(Context context) {
|
||||
mWallpaperManager = WallpaperManagerCompat.getInstance(context);
|
||||
mWallpaperManager.addOnColorsChangedListener(this);
|
||||
mExtractionType = new ColorExtractionAlgorithm();
|
||||
update(mWallpaperManager.getWallpaperColors(FLAG_SYSTEM));
|
||||
}
|
||||
|
||||
public int getMainColor() {
|
||||
return mMainColor;
|
||||
}
|
||||
|
||||
public int getSecondaryColor() {
|
||||
return mSecondaryColor;
|
||||
}
|
||||
|
||||
public boolean isDark() {
|
||||
return mIsDark;
|
||||
}
|
||||
|
||||
public boolean supportsDarkText() {
|
||||
return mSupportsDarkText;
|
||||
}
|
||||
|
||||
public boolean isMainColorDark() {
|
||||
return mMainColor == MAIN_COLOR_DARK;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onColorsChanged(WallpaperColorsCompat colors, int which) {
|
||||
if ((which & FLAG_SYSTEM) != 0) {
|
||||
update(colors);
|
||||
notifyChange();
|
||||
}
|
||||
}
|
||||
|
||||
private void update(WallpaperColorsCompat wallpaperColors) {
|
||||
Pair<Integer, Integer> colors = mExtractionType.extractInto(wallpaperColors);
|
||||
if (colors != null) {
|
||||
mMainColor = colors.first;
|
||||
mSecondaryColor = colors.second;
|
||||
} else {
|
||||
mMainColor = FALLBACK_COLOR;
|
||||
mSecondaryColor = FALLBACK_COLOR;
|
||||
}
|
||||
mSupportsDarkText = wallpaperColors != null
|
||||
? (wallpaperColors.getColorHints()
|
||||
& WallpaperColorsCompat.HINT_SUPPORTS_DARK_TEXT) > 0 : false;
|
||||
mIsDark = wallpaperColors != null
|
||||
? (wallpaperColors.getColorHints()
|
||||
& WallpaperColorsCompat.HINT_SUPPORTS_DARK_THEME) > 0 : false;
|
||||
}
|
||||
|
||||
public void addOnChangeListener(OnChangeListener listener) {
|
||||
mListeners.add(listener);
|
||||
}
|
||||
|
||||
public void removeOnChangeListener(OnChangeListener listener) {
|
||||
mListeners.remove(listener);
|
||||
}
|
||||
|
||||
private void notifyChange() {
|
||||
OnChangeListener[] copy =
|
||||
mTempListeners != null && mTempListeners.length == mListeners.size() ?
|
||||
mTempListeners : new OnChangeListener[mListeners.size()];
|
||||
|
||||
// Create a new array to avoid concurrent modification when the activity destroys itself.
|
||||
mTempListeners = mListeners.toArray(copy);
|
||||
for (OnChangeListener listener : mTempListeners) {
|
||||
listener.onExtractedColorsChanged(this);
|
||||
}
|
||||
}
|
||||
|
||||
public interface OnChangeListener {
|
||||
void onExtractedColorsChanged(WallpaperColorInfo wallpaperColorInfo);
|
||||
}
|
||||
}
|
|
@ -1,795 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 2017 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.android.launcher3.uioverrides.dynamicui;
|
||||
|
||||
import android.graphics.Color;
|
||||
import android.util.Log;
|
||||
import android.util.Pair;
|
||||
import android.util.Range;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.core.graphics.ColorUtils;
|
||||
|
||||
import com.android.launcher3.Utilities;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Implementation of tonal color extraction
|
||||
**/
|
||||
public class ColorExtractionAlgorithm {
|
||||
|
||||
private static final String TAG = "Tonal";
|
||||
|
||||
// Used for tonal palette fitting
|
||||
private static final float FIT_WEIGHT_H = 1.0f;
|
||||
private static final float FIT_WEIGHT_S = 1.0f;
|
||||
private static final float FIT_WEIGHT_L = 10.0f;
|
||||
|
||||
public static final int MAIN_COLOR_LIGHT = 0xffb0b0b0;
|
||||
public static final int SECONDARY_COLOR_LIGHT = 0xff9e9e9e;
|
||||
public static final int MAIN_COLOR_DARK = 0xff212121;
|
||||
public static final int SECONDARY_COLOR_DARK = 0xff000000;
|
||||
|
||||
// Temporary variable to avoid allocations
|
||||
private float[] mTmpHSL = new float[3];
|
||||
|
||||
public Pair<Integer, Integer> extractInto(WallpaperColorsCompat inWallpaperColors) {
|
||||
if (inWallpaperColors == null) {
|
||||
return applyFallback(inWallpaperColors);
|
||||
}
|
||||
|
||||
final List<Integer> mainColors = getMainColors(inWallpaperColors);
|
||||
final int mainColorsSize = mainColors.size();
|
||||
final boolean supportsDarkText = (inWallpaperColors.getColorHints() &
|
||||
WallpaperColorsCompat.HINT_SUPPORTS_DARK_TEXT) != 0;
|
||||
|
||||
if (mainColorsSize == 0) {
|
||||
return applyFallback(inWallpaperColors);
|
||||
}
|
||||
// Tonal is not really a sort, it takes a color from the extracted
|
||||
// palette and finds a best fit amongst a collection of pre-defined
|
||||
// palettes. The best fit is tweaked to be closer to the source color
|
||||
// and replaces the original palette
|
||||
|
||||
// Get the most preeminent, non-disallowed color.
|
||||
Integer bestColor = 0;
|
||||
final float[] hsl = new float[3];
|
||||
for (int i = 0; i < mainColorsSize; i++) {
|
||||
final int colorValue = mainColors.get(i);
|
||||
ColorUtils.RGBToHSL(Color.red(colorValue), Color.green(colorValue),
|
||||
Color.blue(colorValue), hsl);
|
||||
|
||||
// Stop when we find a color that meets our criteria
|
||||
if (!isDisallowed(hsl)) {
|
||||
bestColor = colorValue;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Fail if not found
|
||||
if (bestColor == null) {
|
||||
return applyFallback(inWallpaperColors);
|
||||
}
|
||||
|
||||
int colorValue = bestColor;
|
||||
ColorUtils.RGBToHSL(Color.red(colorValue), Color.green(colorValue), Color.blue(colorValue),
|
||||
hsl);
|
||||
|
||||
// The Android HSL definition requires the hue to go from 0 to 360 but
|
||||
// the Material Tonal Palette defines hues from 0 to 1.
|
||||
hsl[0] /= 360f;
|
||||
|
||||
// Find the palette that contains the closest color
|
||||
TonalPalette palette = findTonalPalette(hsl[0], hsl[1]);
|
||||
if (palette == null) {
|
||||
Log.w(TAG, "Could not find a tonal palette!");
|
||||
return applyFallback(inWallpaperColors);
|
||||
}
|
||||
|
||||
// Figure out what's the main color index in the optimal palette
|
||||
int fitIndex = bestFit(palette, hsl[0], hsl[1], hsl[2]);
|
||||
if (fitIndex == -1) {
|
||||
Log.w(TAG, "Could not find best fit!");
|
||||
return applyFallback(inWallpaperColors);
|
||||
}
|
||||
|
||||
// Generate the 10 colors palette by offsetting each one of them
|
||||
float[] h = fit(palette.h, hsl[0], fitIndex,
|
||||
Float.NEGATIVE_INFINITY, Float.POSITIVE_INFINITY);
|
||||
float[] s = fit(palette.s, hsl[1], fitIndex, 0.0f, 1.0f);
|
||||
float[] l = fit(palette.l, hsl[2], fitIndex, 0.0f, 1.0f);
|
||||
|
||||
int primaryIndex = fitIndex;
|
||||
int mainColor = getColorInt(primaryIndex, h, s, l);
|
||||
|
||||
// We might want use the fallback in case the extracted color is brighter than our
|
||||
// light fallback or darker than our dark fallback.
|
||||
ColorUtils.colorToHSL(mainColor, mTmpHSL);
|
||||
final float mainLuminosity = mTmpHSL[2];
|
||||
ColorUtils.colorToHSL(MAIN_COLOR_LIGHT, mTmpHSL);
|
||||
final float lightLuminosity = mTmpHSL[2];
|
||||
if (mainLuminosity > lightLuminosity) {
|
||||
return applyFallback(inWallpaperColors);
|
||||
}
|
||||
ColorUtils.colorToHSL(MAIN_COLOR_DARK, mTmpHSL);
|
||||
final float darkLuminosity = mTmpHSL[2];
|
||||
if (mainLuminosity < darkLuminosity) {
|
||||
return applyFallback(inWallpaperColors);
|
||||
}
|
||||
|
||||
// Dark colors:
|
||||
// Stops at 4th color, only lighter if dark text is supported
|
||||
if (supportsDarkText) {
|
||||
primaryIndex = h.length - 1;
|
||||
} else if (fitIndex < 2) {
|
||||
primaryIndex = 0;
|
||||
} else {
|
||||
primaryIndex = Math.min(fitIndex, 3);
|
||||
}
|
||||
int secondaryIndex = primaryIndex + (primaryIndex >= 2 ? -2 : 2);
|
||||
int secondaryColor = getColorInt(secondaryIndex, h, s, l);
|
||||
|
||||
return new Pair<>(mainColor, secondaryColor);
|
||||
}
|
||||
|
||||
public static Pair<Integer, Integer> applyFallback(WallpaperColorsCompat inWallpaperColors) {
|
||||
boolean light = inWallpaperColors != null
|
||||
&& (inWallpaperColors.getColorHints()
|
||||
& WallpaperColorsCompat.HINT_SUPPORTS_DARK_TEXT)!= 0;
|
||||
int innerColor = light ? MAIN_COLOR_LIGHT : MAIN_COLOR_DARK;
|
||||
int outerColor = light ? SECONDARY_COLOR_LIGHT : SECONDARY_COLOR_DARK;
|
||||
return new Pair<>(innerColor, outerColor);
|
||||
}
|
||||
|
||||
private int getColorInt(int fitIndex, float[] h, float[] s, float[] l) {
|
||||
mTmpHSL[0] = fract(h[fitIndex]) * 360.0f;
|
||||
mTmpHSL[1] = s[fitIndex];
|
||||
mTmpHSL[2] = l[fitIndex];
|
||||
return ColorUtils.HSLToColor(mTmpHSL);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if a given color exists in the disallowed_colors list.
|
||||
* @param hsl float array with 3 components (H 0..360, S 0..1 and L 0..1)
|
||||
* @return true if color should be avoided
|
||||
*/
|
||||
private boolean isDisallowed(float[] hsl) {
|
||||
for (ColorRange badRange: DISALLOWED_COLORS) {
|
||||
if (badRange.containsColor(hsl[0], hsl[1], hsl[2])) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Offsets all colors by a delta, clamping values that go beyond what's
|
||||
* supported on the color space.
|
||||
* @param data what you want to fit
|
||||
* @param v how big should be the offset
|
||||
* @param index which index to calculate the delta against
|
||||
* @param min minimum accepted value (clamp)
|
||||
* @param max maximum accepted value (clamp)
|
||||
* @return new shifted palette
|
||||
*/
|
||||
private static float[] fit(float[] data, float v, int index, float min, float max) {
|
||||
float[] fitData = new float[data.length];
|
||||
float delta = v - data[index];
|
||||
|
||||
for (int i = 0; i < data.length; i++) {
|
||||
fitData[i] = Utilities.boundToRange(data[i] + delta, min, max);
|
||||
}
|
||||
|
||||
return fitData;
|
||||
}
|
||||
|
||||
/**
|
||||
* Finds the closest color in a palette, given another HSL color
|
||||
*
|
||||
* @param palette where to search
|
||||
* @param h hue
|
||||
* @param s saturation
|
||||
* @param l lightness
|
||||
* @return closest index or -1 if palette is empty.
|
||||
*/
|
||||
private static int bestFit(@NonNull TonalPalette palette, float h, float s, float l) {
|
||||
int minErrorIndex = -1;
|
||||
float minError = Float.POSITIVE_INFINITY;
|
||||
|
||||
for (int i = 0; i < palette.h.length; i++) {
|
||||
float error =
|
||||
FIT_WEIGHT_H * Math.abs(h - palette.h[i])
|
||||
+ FIT_WEIGHT_S * Math.abs(s - palette.s[i])
|
||||
+ FIT_WEIGHT_L * Math.abs(l - palette.l[i]);
|
||||
if (error < minError) {
|
||||
minError = error;
|
||||
minErrorIndex = i;
|
||||
}
|
||||
}
|
||||
|
||||
return minErrorIndex;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private static TonalPalette findTonalPalette(float h, float s) {
|
||||
// Fallback to a grey palette if the color is too desaturated.
|
||||
// This avoids hue shifts.
|
||||
if (s < 0.05f) {
|
||||
return GREY_PALETTE;
|
||||
}
|
||||
|
||||
TonalPalette best = null;
|
||||
float error = Float.POSITIVE_INFINITY;
|
||||
|
||||
for (int i = 0; i < TONAL_PALETTES.length; i++) {
|
||||
final TonalPalette candidate = TONAL_PALETTES[i];
|
||||
|
||||
if (h >= candidate.minHue && h <= candidate.maxHue) {
|
||||
best = candidate;
|
||||
break;
|
||||
}
|
||||
|
||||
if (candidate.maxHue > 1.0f && h >= 0.0f && h <= fract(candidate.maxHue)) {
|
||||
best = candidate;
|
||||
break;
|
||||
}
|
||||
|
||||
if (candidate.minHue < 0.0f && h >= fract(candidate.minHue) && h <= 1.0f) {
|
||||
best = candidate;
|
||||
break;
|
||||
}
|
||||
|
||||
if (h <= candidate.minHue && candidate.minHue - h < error) {
|
||||
best = candidate;
|
||||
error = candidate.minHue - h;
|
||||
} else if (h >= candidate.maxHue && h - candidate.maxHue < error) {
|
||||
best = candidate;
|
||||
error = h - candidate.maxHue;
|
||||
} else if (candidate.maxHue > 1.0f && h >= fract(candidate.maxHue)
|
||||
&& h - fract(candidate.maxHue) < error) {
|
||||
best = candidate;
|
||||
error = h - fract(candidate.maxHue);
|
||||
} else if (candidate.minHue < 0.0f && h <= fract(candidate.minHue)
|
||||
&& fract(candidate.minHue) - h < error) {
|
||||
best = candidate;
|
||||
error = fract(candidate.minHue) - h;
|
||||
}
|
||||
}
|
||||
|
||||
return best;
|
||||
}
|
||||
|
||||
private static float fract(float v) {
|
||||
return v - (float) Math.floor(v);
|
||||
}
|
||||
|
||||
static class TonalPalette {
|
||||
final float[] h;
|
||||
final float[] s;
|
||||
final float[] l;
|
||||
final float minHue;
|
||||
final float maxHue;
|
||||
|
||||
TonalPalette(float[] h, float[] s, float[] l) {
|
||||
if (h.length != s.length || s.length != l.length) {
|
||||
throw new IllegalArgumentException("All arrays should have the same size. h: "
|
||||
+ Arrays.toString(h) + " s: " + Arrays.toString(s) + " l: "
|
||||
+ Arrays.toString(l));
|
||||
}
|
||||
|
||||
this.h = h;
|
||||
this.s = s;
|
||||
this.l = l;
|
||||
|
||||
float minHue = Float.POSITIVE_INFINITY;
|
||||
float maxHue = Float.NEGATIVE_INFINITY;
|
||||
|
||||
for (float v : h) {
|
||||
minHue = Math.min(v, minHue);
|
||||
maxHue = Math.max(v, maxHue);
|
||||
}
|
||||
|
||||
this.minHue = minHue;
|
||||
this.maxHue = maxHue;
|
||||
}
|
||||
}
|
||||
|
||||
// Data definition of Material Design tonal palettes
|
||||
// When the sort type is set to TONAL, these palettes are used to find
|
||||
// a best fit. Each palette is defined as 22 HSL colors
|
||||
private static final TonalPalette[] TONAL_PALETTES = {
|
||||
new TonalPalette(
|
||||
new float[] {1f, 1f, 0.991f, 0.991f, 0.9833333333333333f, 0f, 0f, 0f,
|
||||
0.01134380453752181f, 0.015625000000000003f, 0.024193548387096798f,
|
||||
0.027397260273972573f, 0.017543859649122865f},
|
||||
new float[] {1f, 1f, 1f, 1f, 1f, 1f, 1f, 0.8434782608695652f, 1f, 1f, 1f, 1f,
|
||||
1f},
|
||||
new float[] {0.04f, 0.09f, 0.14f, 0.2f, 0.27450980392156865f,
|
||||
0.34901960784313724f, 0.4235294117647059f, 0.5490196078431373f,
|
||||
0.6254901960784314f, 0.6862745098039216f, 0.7568627450980392f,
|
||||
0.8568627450980393f, 0.9254901960784314f}
|
||||
),
|
||||
new TonalPalette(
|
||||
new float[] {0.638f, 0.638f, 0.6385767790262171f, 0.6301169590643275f,
|
||||
0.6223958333333334f, 0.6151079136690647f, 0.6065400843881856f,
|
||||
0.5986964618249534f, 0.5910746812386157f, 0.5833333333333334f,
|
||||
0.5748031496062993f, 0.5582010582010583f},
|
||||
new float[] {1f, 1f, 1f, 1f, 0.9014084507042253f, 0.8128654970760234f,
|
||||
0.7979797979797981f, 0.7816593886462883f, 0.778723404255319f, 1f, 1f,
|
||||
1f},
|
||||
new float[] {0.05f, 0.12f, 0.17450980392156862f, 0.2235294117647059f,
|
||||
0.2784313725490196f, 0.3352941176470588f, 0.388235294117647f,
|
||||
0.44901960784313727f, 0.5392156862745098f, 0.6509803921568628f,
|
||||
0.7509803921568627f, 0.8764705882352941f}
|
||||
),
|
||||
new TonalPalette(
|
||||
new float[] {0.563f, 0.569f, 0.5666f, 0.5669934640522876f, 0.5748031496062993f,
|
||||
0.5595238095238095f, 0.5473118279569893f, 0.5393258426966292f,
|
||||
0.5315955766192734f, 0.524031007751938f, 0.5154711673699016f,
|
||||
0.508080808080808f, 0.5f},
|
||||
new float[] {1f, 1f, 1f, 1f, 1f, 1f, 1f, 1f, 1f, 0.8847736625514403f, 1f, 1f,
|
||||
1f},
|
||||
new float[] {0.07f, 0.12f, 0.16f, 0.2f, 0.24901960784313726f,
|
||||
0.27450980392156865f, 0.30392156862745096f, 0.34901960784313724f,
|
||||
0.4137254901960784f, 0.47647058823529415f, 0.5352941176470588f,
|
||||
0.6764705882352942f, 0.8f}
|
||||
),
|
||||
new TonalPalette(
|
||||
new float[] {0.508f, 0.511f, 0.508f, 0.508f, 0.5082304526748972f,
|
||||
0.5069444444444444f, 0.5f, 0.5f, 0.5f, 0.48724954462659376f,
|
||||
0.4800347222222222f, 0.4755134281200632f, 0.4724409448818897f,
|
||||
0.4671052631578947f},
|
||||
new float[] {1f, 1f, 1f, 1f, 1f, 0.8888888888888887f, 0.9242424242424242f, 1f,
|
||||
1f, 0.8133333333333332f, 0.7868852459016393f, 1f, 1f, 1f},
|
||||
new float[] {0.04f, 0.06f, 0.08f, 0.12f, 0.1588235294117647f,
|
||||
0.21176470588235297f, 0.25882352941176473f, 0.3f, 0.34901960784313724f,
|
||||
0.44117647058823534f, 0.5215686274509804f, 0.5862745098039216f,
|
||||
0.7509803921568627f, 0.8509803921568627f}
|
||||
),
|
||||
new TonalPalette(
|
||||
new float[] {0.333f, 0.333f, 0.333f, 0.3333333333333333f, 0.3333333333333333f,
|
||||
0.34006734006734f, 0.34006734006734f, 0.34006734006734f,
|
||||
0.34259259259259256f, 0.3475783475783476f, 0.34767025089605735f,
|
||||
0.3467741935483871f, 0.3703703703703704f},
|
||||
new float[] {0.70f, 0.72f, 0.69f, 0.6703296703296703f, 0.728813559322034f,
|
||||
0.5657142857142856f, 0.5076923076923077f, 0.3944223107569721f,
|
||||
0.6206896551724138f, 0.8931297709923666f, 1f, 1f, 1f},
|
||||
new float[] {0.05f, 0.08f, 0.14f, 0.1784313725490196f, 0.23137254901960785f,
|
||||
0.3431372549019608f, 0.38235294117647056f, 0.49215686274509807f,
|
||||
0.6588235294117647f, 0.7431372549019608f, 0.8176470588235294f,
|
||||
0.8784313725490196f, 0.9294117647058824f}
|
||||
),
|
||||
new TonalPalette(
|
||||
new float[] {0.161f, 0.163f, 0.163f, 0.162280701754386f, 0.15032679738562088f,
|
||||
0.15879265091863518f, 0.16236559139784948f, 0.17443868739205526f,
|
||||
0.17824074074074076f, 0.18674698795180725f, 0.18692449355432778f,
|
||||
0.1946778711484594f, 0.18604651162790695f},
|
||||
new float[] {1f, 1f, 1f, 1f, 1f, 1f, 1f, 1f, 1f, 1f, 1f, 1f, 1f},
|
||||
new float[] {0.05f, 0.08f, 0.11f, 0.14901960784313725f, 0.2f,
|
||||
0.24901960784313726f, 0.30392156862745096f, 0.3784313725490196f,
|
||||
0.4235294117647059f, 0.48823529411764705f, 0.6450980392156863f,
|
||||
0.7666666666666666f, 0.8313725490196078f}
|
||||
),
|
||||
new TonalPalette(
|
||||
new float[] {0.108f, 0.105f, 0.105f, 0.105f, 0.10619469026548674f,
|
||||
0.11924686192468618f, 0.13046448087431692f, 0.14248366013071895f,
|
||||
0.1506024096385542f, 0.16220238095238093f, 0.16666666666666666f,
|
||||
0.16666666666666666f, 0.162280701754386f, 0.15686274509803924f},
|
||||
new float[] {1f, 1f, 1f, 1f, 1f, 1f, 1f, 1f, 1f, 1f, 1f, 1f, 1f, 1f},
|
||||
new float[] {0.17f, 0.22f, 0.28f, 0.35f, 0.44313725490196076f,
|
||||
0.46862745098039216f, 0.47843137254901963f, 0.5f, 0.5117647058823529f,
|
||||
0.5607843137254902f, 0.6509803921568628f, 0.7509803921568627f,
|
||||
0.8509803921568627f, 0.9f}
|
||||
),
|
||||
new TonalPalette(
|
||||
new float[] {0.036f, 0.036f, 0.036f, 0.036f, 0.03561253561253561f,
|
||||
0.05098039215686275f, 0.07516339869281045f, 0.09477124183006536f,
|
||||
0.1150326797385621f, 0.134640522875817f, 0.14640522875816991f,
|
||||
0.1582397003745319f, 0.15773809523809523f, 0.15359477124183002f},
|
||||
new float[] {1f, 1f, 1f, 1f, 1f, 1f, 1f, 1f, 1f, 1f, 1f, 1f, 1f, 1f},
|
||||
new float[] {0.19f, 0.26f, 0.34f, 0.39f, 0.4588235294117647f, 0.5f, 0.5f, 0.5f,
|
||||
0.5f, 0.5f, 0.5f, 0.6509803921568628f, 0.7803921568627451f, 0.9f}
|
||||
),
|
||||
new TonalPalette(
|
||||
new float[] {0.955f, 0.961f, 0.958f, 0.9596491228070175f, 0.9593837535014005f,
|
||||
0.9514767932489452f, 0.943859649122807f, 0.9396825396825397f,
|
||||
0.9395424836601307f, 0.9393939393939394f, 0.9362745098039216f,
|
||||
0.9754098360655739f, 0.9824561403508771f},
|
||||
new float[] {0.87f, 0.85f, 0.85f, 0.84070796460177f, 0.8206896551724138f,
|
||||
0.7979797979797981f, 0.7661290322580644f, 0.9051724137931036f,
|
||||
1f, 1f, 1f, 1f, 1f},
|
||||
new float[] {0.06f, 0.11f, 0.16f, 0.22156862745098038f, 0.2843137254901961f,
|
||||
0.388235294117647f, 0.48627450980392156f, 0.5450980392156863f,
|
||||
0.6f, 0.6764705882352942f, 0.8f, 0.8803921568627451f,
|
||||
0.9254901960784314f}
|
||||
),
|
||||
new TonalPalette(
|
||||
new float[] {0.866f, 0.855f, 0.841025641025641f, 0.8333333333333334f,
|
||||
0.8285256410256411f, 0.821522309711286f, 0.8083333333333333f,
|
||||
0.8046594982078853f, 0.8005822416302766f, 0.7842377260981912f,
|
||||
0.7771084337349398f, 0.7747747747747749f},
|
||||
new float[] {1f, 1f, 1f, 1f, 1f, 1f, 1f, 1f, 1f,
|
||||
0.737142857142857f, 0.6434108527131781f, 0.46835443037974644f},
|
||||
new float[] {0.05f, 0.08f, 0.12745098039215685f, 0.15490196078431373f,
|
||||
0.20392156862745098f, 0.24901960784313726f, 0.3137254901960784f,
|
||||
0.36470588235294116f, 0.44901960784313727f, 0.6568627450980392f,
|
||||
0.7470588235294118f, 0.8450980392156863f}
|
||||
),
|
||||
new TonalPalette(
|
||||
new float[] {0.925f, 0.93f, 0.938f, 0.947f, 0.955952380952381f,
|
||||
0.9681069958847737f, 0.9760479041916167f, 0.9873563218390804f, 0f, 0f,
|
||||
0.009057971014492771f, 0.026748971193415648f,
|
||||
0.041666666666666616f, 0.05303030303030304f},
|
||||
new float[] {1f, 1f, 1f, 1f, 1f, 0.8350515463917526f, 0.6929460580912863f,
|
||||
0.6387665198237885f, 0.6914893617021276f, 0.7583892617449666f,
|
||||
0.8070175438596495f, 0.9310344827586209f, 1f, 1f},
|
||||
new float[] {0.10f, 0.13f, 0.17f, 0.2f, 0.27450980392156865f,
|
||||
0.3803921568627451f, 0.4725490196078432f, 0.5549019607843138f,
|
||||
0.6313725490196078f, 0.707843137254902f, 0.7764705882352941f,
|
||||
0.8294117647058823f, 0.9058823529411765f, 0.9568627450980391f}
|
||||
),
|
||||
new TonalPalette(
|
||||
new float[] {0.733f, 0.736f, 0.744f, 0.7514619883040936f, 0.7679738562091503f,
|
||||
0.7802083333333333f, 0.7844311377245509f, 0.796875f,
|
||||
0.8165618448637316f, 0.8487179487179487f, 0.8582375478927203f,
|
||||
0.8562091503267975f, 0.8666666666666667f},
|
||||
new float[] {1f, 1f, 1f, 1f, 1f, 0.8163265306122449f, 0.6653386454183268f,
|
||||
0.7547169811320753f, 0.929824561403509f, 0.9558823529411766f,
|
||||
0.9560439560439562f, 1f, 1f},
|
||||
new float[] {0.07f, 0.12f, 0.17f, 0.2235294117647059f, 0.3f,
|
||||
0.38431372549019605f, 0.492156862745098f, 0.5843137254901961f,
|
||||
0.6647058823529411f, 0.7333333333333334f, 0.8215686274509804f, 0.9f,
|
||||
0.9411764705882353f}
|
||||
),
|
||||
new TonalPalette(
|
||||
new float[] {0.6666666666666666f, 0.6666666666666666f, 0.6666666666666666f,
|
||||
0.6666666666666666f, 0.6666666666666666f, 0.6666666666666666f,
|
||||
0.6666666666666666f, 0.6666666666666666f, 0.6666666666666666f,
|
||||
0.6666666666666666f, 0.6666666666666666f},
|
||||
new float[] {0.25f, 0.24590163934426232f, 0.17880794701986752f,
|
||||
0.14606741573033713f, 0.13761467889908252f, 0.14893617021276592f,
|
||||
0.16756756756756758f, 0.20312500000000017f, 0.26086956521739135f,
|
||||
0.29999999999999966f, 0.5000000000000004f},
|
||||
new float[] {0.18f, 0.2392156862745098f, 0.296078431372549f,
|
||||
0.34901960784313724f, 0.4274509803921569f, 0.5392156862745098f,
|
||||
0.6372549019607843f, 0.7490196078431373f, 0.8196078431372549f,
|
||||
0.8823529411764706f, 0.9372549019607843f}
|
||||
),
|
||||
new TonalPalette(
|
||||
new float[] {0.938f, 0.944f, 0.952f, 0.961f, 0.9678571428571429f,
|
||||
0.9944812362030905f, 0f, 0f,
|
||||
0.0047348484848484815f, 0.00316455696202532f, 0f,
|
||||
0.9980392156862745f, 0.9814814814814816f, 0.9722222222222221f},
|
||||
new float[] {1f, 1f, 1f, 1f, 1f, 0.7023255813953488f, 0.6638655462184874f,
|
||||
0.6521739130434782f, 0.7719298245614035f, 0.8315789473684211f,
|
||||
0.6867469879518071f, 0.7264957264957265f, 0.8181818181818182f,
|
||||
0.8181818181818189f},
|
||||
new float[] {0.08f, 0.13f, 0.18f, 0.23f, 0.27450980392156865f,
|
||||
0.4215686274509804f,
|
||||
0.4666666666666667f, 0.503921568627451f, 0.5529411764705883f,
|
||||
0.6274509803921569f, 0.6745098039215687f, 0.7705882352941176f,
|
||||
0.892156862745098f, 0.9568627450980391f}
|
||||
),
|
||||
new TonalPalette(
|
||||
new float[] {0.88f, 0.888f, 0.897f, 0.9052287581699346f, 0.9112021857923498f,
|
||||
0.9270152505446624f, 0.9343137254901961f, 0.9391534391534391f,
|
||||
0.9437984496124031f, 0.943661971830986f, 0.9438943894389439f,
|
||||
0.9426229508196722f, 0.9444444444444444f},
|
||||
new float[] {1f, 1f, 1f, 1f, 0.8133333333333332f, 0.7927461139896375f,
|
||||
0.7798165137614679f, 0.7777777777777779f, 0.8190476190476191f,
|
||||
0.8255813953488372f, 0.8211382113821142f, 0.8133333333333336f,
|
||||
0.8000000000000006f},
|
||||
new float[] {0.08f, 0.12f, 0.16f, 0.2f, 0.29411764705882354f,
|
||||
0.3784313725490196f, 0.42745098039215684f, 0.4764705882352941f,
|
||||
0.5882352941176471f, 0.6627450980392157f, 0.7588235294117647f,
|
||||
0.8529411764705882f, 0.9411764705882353f}
|
||||
),
|
||||
new TonalPalette(
|
||||
new float[] {0.669f, 0.680f, 0.6884057971014492f, 0.6974789915966387f,
|
||||
0.7079889807162534f, 0.7154471544715447f, 0.7217741935483872f,
|
||||
0.7274143302180687f, 0.7272727272727273f, 0.7258064516129031f,
|
||||
0.7252252252252251f, 0.7333333333333333f},
|
||||
new float[] {0.81f, 0.81f, 0.8214285714285715f, 0.6878612716763006f,
|
||||
0.6080402010050251f, 0.5774647887323943f, 0.5391304347826086f,
|
||||
0.46724890829694316f, 0.4680851063829788f, 0.462686567164179f,
|
||||
0.45679012345678977f, 0.4545454545454551f},
|
||||
new float[] {0.12f, 0.16f, 0.2196078431372549f, 0.33921568627450976f,
|
||||
0.39019607843137255f, 0.4176470588235294f, 0.45098039215686275f,
|
||||
0.5509803921568628f, 0.6313725490196078f, 0.7372549019607844f,
|
||||
0.8411764705882353f, 0.9352941176470588f}
|
||||
),
|
||||
new TonalPalette(
|
||||
new float[] {0.6470588235294118f, 0.6516666666666667f, 0.6464174454828661f,
|
||||
0.6441441441441442f, 0.6432748538011696f, 0.6416666666666667f,
|
||||
0.6402439024390243f, 0.6412429378531074f, 0.6435185185185186f,
|
||||
0.6428571428571429f},
|
||||
new float[] {0.8095238095238095f, 0.6578947368421053f, 0.5721925133689839f,
|
||||
0.5362318840579711f, 0.5f, 0.4424778761061947f, 0.44086021505376327f,
|
||||
0.44360902255639095f, 0.4499999999999997f, 0.4375000000000006f},
|
||||
new float[] {0.16470588235294117f, 0.2980392156862745f, 0.36666666666666664f,
|
||||
0.40588235294117647f, 0.44705882352941173f,
|
||||
0.5568627450980392f, 0.6352941176470588f, 0.7392156862745098f,
|
||||
0.8431372549019608f, 0.9372549019607843f}
|
||||
),
|
||||
new TonalPalette(
|
||||
new float[] {0.469f, 0.46732026143790845f, 0.4718614718614719f,
|
||||
0.4793650793650794f, 0.48071625344352614f, 0.4829683698296837f,
|
||||
0.484375f, 0.4841269841269842f, 0.48444444444444457f,
|
||||
0.48518518518518516f, 0.4907407407407408f},
|
||||
new float[] {1f, 1f, 1f, 1f, 1f, 1f, 0.6274509803921569f, 0.41832669322709176f,
|
||||
0.41899441340782106f, 0.4128440366972478f, 0.4090909090909088f},
|
||||
new float[] {0.07f, 0.1f, 0.15098039215686274f, 0.20588235294117646f,
|
||||
0.2372549019607843f, 0.26862745098039215f, 0.4f, 0.5078431372549019f,
|
||||
0.6490196078431372f, 0.7862745098039216f, 0.9137254901960784f}
|
||||
),
|
||||
new TonalPalette(
|
||||
new float[] {0.542f, 0.5444444444444444f, 0.5555555555555556f,
|
||||
0.5555555555555556f, 0.553763440860215f, 0.5526315789473684f,
|
||||
0.5555555555555556f, 0.5555555555555555f, 0.5555555555555556f,
|
||||
0.5512820512820514f, 0.5666666666666667f},
|
||||
new float[] {0.25f, 0.24590163934426232f, 0.19148936170212766f,
|
||||
0.1791044776119403f, 0.18343195266272191f, 0.18446601941747576f,
|
||||
0.1538461538461539f, 0.15625000000000003f, 0.15328467153284678f,
|
||||
0.15662650602409653f, 0.151515151515151f},
|
||||
new float[] {0.05f, 0.1196078431372549f, 0.1843137254901961f,
|
||||
0.2627450980392157f,
|
||||
0.33137254901960783f, 0.403921568627451f, 0.5411764705882354f,
|
||||
0.6235294117647059f, 0.7313725490196079f, 0.8372549019607843f,
|
||||
0.9352941176470588f}
|
||||
),
|
||||
new TonalPalette(
|
||||
new float[] {0.022222222222222223f, 0.02469135802469136f, 0.031249999999999997f,
|
||||
0.03947368421052631f, 0.04166666666666668f,
|
||||
0.043650793650793655f, 0.04411764705882352f, 0.04166666666666652f,
|
||||
0.04444444444444459f, 0.05555555555555529f},
|
||||
new float[] {0.33333333333333337f, 0.2783505154639175f, 0.2580645161290323f,
|
||||
0.25675675675675674f, 0.2528735632183908f, 0.17500000000000002f,
|
||||
0.15315315315315312f, 0.15189873417721522f,
|
||||
0.15789473684210534f, 0.15789473684210542f},
|
||||
new float[] {0.08823529411764705f, 0.19019607843137254f, 0.2431372549019608f,
|
||||
0.2901960784313725f, 0.3411764705882353f, 0.47058823529411764f,
|
||||
0.5647058823529412f, 0.6901960784313725f, 0.8137254901960784f,
|
||||
0.9254901960784314f}
|
||||
),
|
||||
new TonalPalette(
|
||||
new float[] {0.027f, 0.03f, 0.038f, 0.044f, 0.050884955752212385f,
|
||||
0.07254901960784313f, 0.0934640522875817f,
|
||||
0.10457516339869281f, 0.11699346405228758f,
|
||||
0.1255813953488372f, 0.1268939393939394f, 0.12533333333333332f,
|
||||
0.12500000000000003f, 0.12777777777777777f},
|
||||
new float[] {1f, 1f, 1f, 1f, 1f, 1f, 1f, 1f, 1f, 1f, 1f, 1f, 1f, 1f},
|
||||
new float[] {0.25f, 0.3f, 0.35f, 0.4f, 0.44313725490196076f, 0.5f, 0.5f, 0.5f,
|
||||
0.5f, 0.5784313725490196f,
|
||||
0.6549019607843137f, 0.7549019607843137f, 0.8509803921568627f,
|
||||
0.9411764705882353f}
|
||||
)
|
||||
};
|
||||
|
||||
private static final TonalPalette GREY_PALETTE = new TonalPalette(
|
||||
new float[]{0f, 0f, 0f, 0f, 0f, 0f, 0f, 0f, 0f, 0f, 0f, 0f},
|
||||
new float[]{0f, 0f, 0f, 0f, 0f, 0f, 0f, 0f, 0f, 0f, 0f, 0f},
|
||||
new float[]{0.08f, 0.11f, 0.14901960784313725f, 0.2f, 0.2980392156862745f, 0.4f,
|
||||
0.4980392156862745f, 0.6196078431372549f, 0.7176470588235294f,
|
||||
0.8196078431372549f, 0.9176470588235294f, 0.9490196078431372f}
|
||||
);
|
||||
|
||||
@SuppressWarnings("WeakerAccess")
|
||||
static final ColorRange[] DISALLOWED_COLORS = new ColorRange[] {
|
||||
|
||||
// Red
|
||||
new ColorRange(
|
||||
new Range<>(0f, 20f) /* H */,
|
||||
new Range<>(0.7f, 1f) /* S */,
|
||||
new Range<>(0.21f, 0.79f)) /* L */,
|
||||
new ColorRange(
|
||||
new Range<>(0f, 20f),
|
||||
new Range<>(0.3f, 0.7f),
|
||||
new Range<>(0.355f, 0.653f)),
|
||||
|
||||
// Red Orange
|
||||
new ColorRange(
|
||||
new Range<>(20f, 40f),
|
||||
new Range<>(0.7f, 1f),
|
||||
new Range<>(0.28f, 0.643f)),
|
||||
new ColorRange(
|
||||
new Range<>(20f, 40f),
|
||||
new Range<>(0.3f, 0.7f),
|
||||
new Range<>(0.414f, 0.561f)),
|
||||
new ColorRange(
|
||||
new Range<>(20f, 40f),
|
||||
new Range<>(0f, 3f),
|
||||
new Range<>(0.343f, 0.584f)),
|
||||
|
||||
// Orange
|
||||
new ColorRange(
|
||||
new Range<>(40f, 60f),
|
||||
new Range<>(0.7f, 1f),
|
||||
new Range<>(0.173f, 0.349f)),
|
||||
new ColorRange(
|
||||
new Range<>(40f, 60f),
|
||||
new Range<>(0.3f, 0.7f),
|
||||
new Range<>(0.233f, 0.427f)),
|
||||
new ColorRange(
|
||||
new Range<>(40f, 60f),
|
||||
new Range<>(0f, 0.3f),
|
||||
new Range<>(0.231f, 0.484f)),
|
||||
|
||||
// Yellow 60
|
||||
new ColorRange(
|
||||
new Range<>(60f, 80f),
|
||||
new Range<>(0.7f, 1f),
|
||||
new Range<>(0.488f, 0.737f)),
|
||||
new ColorRange(
|
||||
new Range<>(60f, 80f),
|
||||
new Range<>(0.3f, 0.7f),
|
||||
new Range<>(0.673f, 0.837f)),
|
||||
|
||||
// Yellow Green 80
|
||||
new ColorRange(
|
||||
new Range<>(80f, 100f),
|
||||
new Range<>(0.7f, 1f),
|
||||
new Range<>(0.469f, 0.61f)),
|
||||
|
||||
// Yellow green 100
|
||||
new ColorRange(
|
||||
new Range<>(100f, 120f),
|
||||
new Range<>(0.7f, 1f),
|
||||
new Range<>(0.388f, 0.612f)),
|
||||
new ColorRange(
|
||||
new Range<>(100f, 120f),
|
||||
new Range<>(0.3f, 0.7f),
|
||||
new Range<>(0.424f, 0.541f)),
|
||||
|
||||
// Green
|
||||
new ColorRange(
|
||||
new Range<>(120f, 140f),
|
||||
new Range<>(0.7f, 1f),
|
||||
new Range<>(0.375f, 0.52f)),
|
||||
new ColorRange(
|
||||
new Range<>(120f, 140f),
|
||||
new Range<>(0.3f, 0.7f),
|
||||
new Range<>(0.435f, 0.524f)),
|
||||
|
||||
// Green Blue 140
|
||||
new ColorRange(
|
||||
new Range<>(140f, 160f),
|
||||
new Range<>(0.7f, 1f),
|
||||
new Range<>(0.496f, 0.641f)),
|
||||
|
||||
// Seafoam
|
||||
new ColorRange(
|
||||
new Range<>(160f, 180f),
|
||||
new Range<>(0.7f, 1f),
|
||||
new Range<>(0.496f, 0.567f)),
|
||||
|
||||
// Cyan
|
||||
new ColorRange(
|
||||
new Range<>(180f, 200f),
|
||||
new Range<>(0.7f, 1f),
|
||||
new Range<>(0.52f, 0.729f)),
|
||||
|
||||
// Blue
|
||||
new ColorRange(
|
||||
new Range<>(220f, 240f),
|
||||
new Range<>(0.7f, 1f),
|
||||
new Range<>(0.396f, 0.571f)),
|
||||
new ColorRange(
|
||||
new Range<>(220f, 240f),
|
||||
new Range<>(0.3f, 0.7f),
|
||||
new Range<>(0.425f, 0.551f)),
|
||||
|
||||
// Blue Purple 240
|
||||
new ColorRange(
|
||||
new Range<>(240f, 260f),
|
||||
new Range<>(0.7f, 1f),
|
||||
new Range<>(0.418f, 0.639f)),
|
||||
new ColorRange(
|
||||
new Range<>(220f, 240f),
|
||||
new Range<>(0.3f, 0.7f),
|
||||
new Range<>(0.441f, 0.576f)),
|
||||
|
||||
// Blue Purple 260
|
||||
new ColorRange(
|
||||
new Range<>(260f, 280f),
|
||||
new Range<>(0.3f, 1f), // Bigger range
|
||||
new Range<>(0.461f, 0.553f)),
|
||||
|
||||
// Fuchsia
|
||||
new ColorRange(
|
||||
new Range<>(300f, 320f),
|
||||
new Range<>(0.7f, 1f),
|
||||
new Range<>(0.484f, 0.588f)),
|
||||
new ColorRange(
|
||||
new Range<>(300f, 320f),
|
||||
new Range<>(0.3f, 0.7f),
|
||||
new Range<>(0.48f, 0.592f)),
|
||||
|
||||
// Pink
|
||||
new ColorRange(
|
||||
new Range<>(320f, 340f),
|
||||
new Range<>(0.7f, 1f),
|
||||
new Range<>(0.466f, 0.629f)),
|
||||
|
||||
// Soft red
|
||||
new ColorRange(
|
||||
new Range<>(340f, 360f),
|
||||
new Range<>(0.7f, 1f),
|
||||
new Range<>(0.437f, 0.596f))
|
||||
};
|
||||
|
||||
/**
|
||||
* Representation of an HSL color range.
|
||||
* <ul>
|
||||
* <li>hsl[0] is Hue [0 .. 360)</li>
|
||||
* <li>hsl[1] is Saturation [0...1]</li>
|
||||
* <li>hsl[2] is Lightness [0...1]</li>
|
||||
* </ul>
|
||||
*/
|
||||
static class ColorRange {
|
||||
private Range<Float> mHue;
|
||||
private Range<Float> mSaturation;
|
||||
private Range<Float> mLightness;
|
||||
|
||||
ColorRange(Range<Float> hue, Range<Float> saturation, Range<Float> lightness) {
|
||||
mHue = hue;
|
||||
mSaturation = saturation;
|
||||
mLightness = lightness;
|
||||
}
|
||||
|
||||
boolean containsColor(float h, float s, float l) {
|
||||
if (!mHue.contains(h)) {
|
||||
return false;
|
||||
} else if (!mSaturation.contains(s)) {
|
||||
return false;
|
||||
} else if (!mLightness.contains(l)) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
float[] getCenter() {
|
||||
return new float[] {
|
||||
mHue.getLower() + (mHue.getUpper() - mHue.getLower()) / 2f,
|
||||
mSaturation.getLower() + (mSaturation.getUpper() - mSaturation.getLower()) / 2f,
|
||||
mLightness.getLower() + (mLightness.getUpper() - mLightness.getLower()) / 2f
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return String.format("H: %s, S: %s, L %s", mHue, mSaturation, mLightness);
|
||||
}
|
||||
}
|
||||
|
||||
private static List<Integer> getMainColors(WallpaperColorsCompat wallpaperColors) {
|
||||
LinkedList<Integer> colors = new LinkedList<>();
|
||||
if (wallpaperColors.getPrimaryColor() != 0) {
|
||||
colors.add(wallpaperColors.getPrimaryColor());
|
||||
}
|
||||
if (wallpaperColors.getSecondaryColor() != 0) {
|
||||
colors.add(wallpaperColors.getSecondaryColor());
|
||||
}
|
||||
if (wallpaperColors.getTertiaryColor() != 0) {
|
||||
colors.add(wallpaperColors.getTertiaryColor());
|
||||
}
|
||||
return colors;
|
||||
}
|
||||
}
|
|
@ -1,55 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 2017 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.android.launcher3.uioverrides.dynamicui;
|
||||
|
||||
/**
|
||||
* A compatibility layer around platform implementation of WallpaperColors
|
||||
*/
|
||||
public class WallpaperColorsCompat {
|
||||
|
||||
public static final int HINT_SUPPORTS_DARK_TEXT = 0x1;
|
||||
public static final int HINT_SUPPORTS_DARK_THEME = 0x2;
|
||||
|
||||
private final int mPrimaryColor;
|
||||
private final int mSecondaryColor;
|
||||
private final int mTertiaryColor;
|
||||
private final int mColorHints;
|
||||
|
||||
public WallpaperColorsCompat(int primaryColor, int secondaryColor, int tertiaryColor,
|
||||
int colorHints) {
|
||||
mPrimaryColor = primaryColor;
|
||||
mSecondaryColor = secondaryColor;
|
||||
mTertiaryColor = tertiaryColor;
|
||||
mColorHints = colorHints;
|
||||
}
|
||||
|
||||
public int getPrimaryColor() {
|
||||
return mPrimaryColor;
|
||||
}
|
||||
|
||||
public int getSecondaryColor() {
|
||||
return mSecondaryColor;
|
||||
}
|
||||
|
||||
public int getTertiaryColor() {
|
||||
return mTertiaryColor;
|
||||
}
|
||||
|
||||
public int getColorHints() {
|
||||
return mColorHints;
|
||||
}
|
||||
|
||||
}
|
|
@ -1,61 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 2017 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.android.launcher3.uioverrides.dynamicui;
|
||||
|
||||
import android.content.Context;
|
||||
import android.os.Build;
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
public abstract class WallpaperManagerCompat {
|
||||
|
||||
private static final Object sInstanceLock = new Object();
|
||||
private static WallpaperManagerCompat sInstance;
|
||||
|
||||
public static WallpaperManagerCompat getInstance(Context context) {
|
||||
synchronized (sInstanceLock) {
|
||||
if (sInstance == null) {
|
||||
context = context.getApplicationContext();
|
||||
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O_MR1) {
|
||||
try {
|
||||
sInstance = new WallpaperManagerCompatVOMR1(context);
|
||||
} catch (Throwable e) {
|
||||
// The wallpaper APIs do not yet exist
|
||||
}
|
||||
}
|
||||
if (sInstance == null) {
|
||||
sInstance = new WallpaperManagerCompatVL(context);
|
||||
}
|
||||
}
|
||||
return sInstance;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public abstract @Nullable WallpaperColorsCompat getWallpaperColors(int which);
|
||||
|
||||
public abstract void addOnColorsChangedListener(OnColorsChangedListenerCompat listener);
|
||||
|
||||
/**
|
||||
* Interface definition for a callback to be invoked when colors change on a wallpaper.
|
||||
*/
|
||||
public interface OnColorsChangedListenerCompat {
|
||||
|
||||
void onColorsChanged(WallpaperColorsCompat colors, int which);
|
||||
}
|
||||
}
|
|
@ -1,271 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 2017 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.android.launcher3.uioverrides.dynamicui;
|
||||
|
||||
import static android.app.WallpaperManager.FLAG_SYSTEM;
|
||||
|
||||
import static com.android.launcher3.Utilities.getDevicePrefs;
|
||||
|
||||
import android.app.WallpaperInfo;
|
||||
import android.app.WallpaperManager;
|
||||
import android.app.job.JobInfo;
|
||||
import android.app.job.JobParameters;
|
||||
import android.app.job.JobScheduler;
|
||||
import android.app.job.JobService;
|
||||
import android.content.BroadcastReceiver;
|
||||
import android.content.ComponentName;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.IntentFilter;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.content.pm.PermissionInfo;
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.BitmapFactory;
|
||||
import android.graphics.BitmapRegionDecoder;
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.Rect;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.os.Handler;
|
||||
import android.os.HandlerThread;
|
||||
import android.os.ParcelFileDescriptor;
|
||||
import android.util.Log;
|
||||
import android.util.Pair;
|
||||
|
||||
import com.android.launcher3.icons.ColorExtractor;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
public class WallpaperManagerCompatVL extends WallpaperManagerCompat {
|
||||
|
||||
private static final String TAG = "WMCompatVL";
|
||||
|
||||
private static final String VERSION_PREFIX = "1,";
|
||||
private static final String KEY_COLORS = "wallpaper_parsed_colors";
|
||||
private static final String ACTION_EXTRACTION_COMPLETE =
|
||||
"com.android.launcher3.uioverrides.dynamicui.WallpaperManagerCompatVL.EXTRACTION_COMPLETE";
|
||||
|
||||
public static final int WALLPAPER_COMPAT_JOB_ID = 1;
|
||||
|
||||
private final ArrayList<OnColorsChangedListenerCompat> mListeners = new ArrayList<>();
|
||||
|
||||
private final Context mContext;
|
||||
private WallpaperColorsCompat mColorsCompat;
|
||||
|
||||
WallpaperManagerCompatVL(Context context) {
|
||||
mContext = context;
|
||||
|
||||
String colors = getDevicePrefs(mContext).getString(KEY_COLORS, "");
|
||||
int wallpaperId = -1;
|
||||
if (colors.startsWith(VERSION_PREFIX)) {
|
||||
Pair<Integer, WallpaperColorsCompat> storedValue = parseValue(colors);
|
||||
wallpaperId = storedValue.first;
|
||||
mColorsCompat = storedValue.second;
|
||||
}
|
||||
|
||||
if (wallpaperId == -1 || wallpaperId != getWallpaperId(context)) {
|
||||
reloadColors();
|
||||
}
|
||||
context.registerReceiver(new BroadcastReceiver() {
|
||||
@Override
|
||||
public void onReceive(Context context, Intent intent) {
|
||||
reloadColors();
|
||||
}
|
||||
}, new IntentFilter(Intent.ACTION_WALLPAPER_CHANGED));
|
||||
|
||||
// Register a receiver for results
|
||||
String permission = null;
|
||||
// Find a permission which only we can use.
|
||||
try {
|
||||
for (PermissionInfo info : context.getPackageManager().getPackageInfo(
|
||||
context.getPackageName(),
|
||||
PackageManager.GET_PERMISSIONS).permissions) {
|
||||
if ((info.protectionLevel & PermissionInfo.PROTECTION_SIGNATURE) != 0) {
|
||||
permission = info.name;
|
||||
}
|
||||
}
|
||||
} catch (PackageManager.NameNotFoundException e) {
|
||||
// Something went wrong. ignore
|
||||
Log.d(TAG, "Unable to get permission info", e);
|
||||
}
|
||||
mContext.registerReceiver(new BroadcastReceiver() {
|
||||
@Override
|
||||
public void onReceive(Context context, Intent intent) {
|
||||
handleResult(intent.getStringExtra(KEY_COLORS));
|
||||
}
|
||||
}, new IntentFilter(ACTION_EXTRACTION_COMPLETE), permission, new Handler());
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public WallpaperColorsCompat getWallpaperColors(int which) {
|
||||
return which == FLAG_SYSTEM ? mColorsCompat : null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addOnColorsChangedListener(OnColorsChangedListenerCompat listener) {
|
||||
mListeners.add(listener);
|
||||
}
|
||||
|
||||
private void reloadColors() {
|
||||
JobInfo job = new JobInfo.Builder(WALLPAPER_COMPAT_JOB_ID,
|
||||
new ComponentName(mContext, ColorExtractionService.class))
|
||||
.setMinimumLatency(0).build();
|
||||
((JobScheduler) mContext.getSystemService(Context.JOB_SCHEDULER_SERVICE)).schedule(job);
|
||||
}
|
||||
|
||||
private void handleResult(String result) {
|
||||
getDevicePrefs(mContext).edit().putString(KEY_COLORS, result).apply();
|
||||
mColorsCompat = parseValue(result).second;
|
||||
for (OnColorsChangedListenerCompat listener : mListeners) {
|
||||
listener.onColorsChanged(mColorsCompat, FLAG_SYSTEM);
|
||||
}
|
||||
}
|
||||
|
||||
private static final int getWallpaperId(Context context) {
|
||||
return context.getSystemService(WallpaperManager.class).getWallpaperId(FLAG_SYSTEM);
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses the stored value and returns the wallpaper id and wallpaper colors.
|
||||
*/
|
||||
private static Pair<Integer, WallpaperColorsCompat> parseValue(String value) {
|
||||
String[] parts = value.split(",");
|
||||
Integer wallpaperId = Integer.parseInt(parts[1]);
|
||||
if (parts.length == 2) {
|
||||
// There is no wallpaper color info present, eg when live wallpaper has no preview.
|
||||
return Pair.create(wallpaperId, null);
|
||||
}
|
||||
|
||||
int primary = parts.length > 2 ? Integer.parseInt(parts[2]) : 0;
|
||||
int secondary = parts.length > 3 ? Integer.parseInt(parts[3]) : 0;
|
||||
int tertiary = parts.length > 4 ? Integer.parseInt(parts[4]) : 0;
|
||||
|
||||
return Pair.create(wallpaperId, new WallpaperColorsCompat(primary, secondary, tertiary,
|
||||
0 /* hints */));
|
||||
}
|
||||
|
||||
/**
|
||||
* Intent service to handle color extraction
|
||||
*/
|
||||
public static class ColorExtractionService extends JobService implements Runnable {
|
||||
private static final int MAX_WALLPAPER_EXTRACTION_AREA = 112 * 112;
|
||||
|
||||
private HandlerThread mWorkerThread;
|
||||
private Handler mWorkerHandler;
|
||||
private ColorExtractor mColorExtractor;
|
||||
|
||||
@Override
|
||||
public void onCreate() {
|
||||
super.onCreate();
|
||||
mWorkerThread = new HandlerThread("ColorExtractionService");
|
||||
mWorkerThread.start();
|
||||
mWorkerHandler = new Handler(mWorkerThread.getLooper());
|
||||
mColorExtractor = new ColorExtractor();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDestroy() {
|
||||
super.onDestroy();
|
||||
mWorkerThread.quit();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onStartJob(final JobParameters jobParameters) {
|
||||
mWorkerHandler.post(this);
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onStopJob(JobParameters jobParameters) {
|
||||
mWorkerHandler.removeCallbacksAndMessages(null);
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Extracts the wallpaper colors and sends the result back through the receiver.
|
||||
*/
|
||||
@Override
|
||||
public void run() {
|
||||
int wallpaperId = getWallpaperId(this);
|
||||
|
||||
Bitmap bitmap = null;
|
||||
Drawable drawable = null;
|
||||
|
||||
WallpaperManager wm = WallpaperManager.getInstance(this);
|
||||
WallpaperInfo info = wm.getWallpaperInfo();
|
||||
if (info != null) {
|
||||
// For live wallpaper, extract colors from thumbnail
|
||||
drawable = info.loadThumbnail(getPackageManager());
|
||||
} else {
|
||||
try (ParcelFileDescriptor fd = wm.getWallpaperFile(FLAG_SYSTEM)) {
|
||||
BitmapRegionDecoder decoder = BitmapRegionDecoder
|
||||
.newInstance(fd.getFileDescriptor(), false);
|
||||
|
||||
int requestedArea = decoder.getWidth() * decoder.getHeight();
|
||||
BitmapFactory.Options options = new BitmapFactory.Options();
|
||||
|
||||
if (requestedArea > MAX_WALLPAPER_EXTRACTION_AREA) {
|
||||
double areaRatio =
|
||||
(double) requestedArea / MAX_WALLPAPER_EXTRACTION_AREA;
|
||||
double nearestPowOf2 =
|
||||
Math.floor(Math.log(areaRatio) / (2 * Math.log(2)));
|
||||
options.inSampleSize = (int) Math.pow(2, nearestPowOf2);
|
||||
}
|
||||
Rect region = new Rect(0, 0, decoder.getWidth(), decoder.getHeight());
|
||||
bitmap = decoder.decodeRegion(region, options);
|
||||
decoder.recycle();
|
||||
} catch (IOException | NullPointerException e) {
|
||||
Log.e(TAG, "Fetching partial bitmap failed, trying old method", e);
|
||||
}
|
||||
if (bitmap == null) {
|
||||
drawable = wm.getDrawable();
|
||||
}
|
||||
}
|
||||
|
||||
if (drawable != null) {
|
||||
// Calculate how big the bitmap needs to be.
|
||||
// This avoids unnecessary processing and allocation inside Palette.
|
||||
final int requestedArea = drawable.getIntrinsicWidth() *
|
||||
drawable.getIntrinsicHeight();
|
||||
double scale = 1;
|
||||
if (requestedArea > MAX_WALLPAPER_EXTRACTION_AREA) {
|
||||
scale = Math.sqrt(MAX_WALLPAPER_EXTRACTION_AREA / (double) requestedArea);
|
||||
}
|
||||
bitmap = Bitmap.createBitmap((int) (drawable.getIntrinsicWidth() * scale),
|
||||
(int) (drawable.getIntrinsicHeight() * scale), Bitmap.Config.ARGB_8888);
|
||||
final Canvas bmpCanvas = new Canvas(bitmap);
|
||||
drawable.setBounds(0, 0, bitmap.getWidth(), bitmap.getHeight());
|
||||
drawable.draw(bmpCanvas);
|
||||
}
|
||||
|
||||
String value = VERSION_PREFIX + wallpaperId;
|
||||
|
||||
if (bitmap != null) {
|
||||
int color = mColorExtractor.findDominantColorByHue(bitmap,
|
||||
MAX_WALLPAPER_EXTRACTION_AREA);
|
||||
value += "," + color;
|
||||
}
|
||||
|
||||
// Send the result
|
||||
sendBroadcast(new Intent(ACTION_EXTRACTION_COMPLETE)
|
||||
.setPackage(getPackageName())
|
||||
.putExtra(KEY_COLORS, value));
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,85 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 2017 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.android.launcher3.uioverrides.dynamicui;
|
||||
|
||||
import android.annotation.TargetApi;
|
||||
import android.app.WallpaperColors;
|
||||
import android.app.WallpaperManager;
|
||||
import android.app.WallpaperManager.OnColorsChangedListener;
|
||||
import android.content.Context;
|
||||
import android.graphics.Color;
|
||||
import android.util.Log;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
@TargetApi(27)
|
||||
public class WallpaperManagerCompatVOMR1 extends WallpaperManagerCompat {
|
||||
|
||||
private static final String TAG = "WMCompatVOMR1";
|
||||
|
||||
private final WallpaperManager mWm;
|
||||
private Method mWCColorHintsMethod;
|
||||
|
||||
WallpaperManagerCompatVOMR1(Context context) throws Throwable {
|
||||
mWm = context.getSystemService(WallpaperManager.class);
|
||||
String className = WallpaperColors.class.getName();
|
||||
try {
|
||||
mWCColorHintsMethod = WallpaperColors.class.getDeclaredMethod("getColorHints");
|
||||
} catch (Exception exc) {
|
||||
Log.e(TAG, "getColorHints not available", exc);
|
||||
}
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public WallpaperColorsCompat getWallpaperColors(int which) {
|
||||
return convertColorsObject(mWm.getWallpaperColors(which));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addOnColorsChangedListener(final OnColorsChangedListenerCompat listener) {
|
||||
OnColorsChangedListener onChangeListener = new OnColorsChangedListener() {
|
||||
@Override
|
||||
public void onColorsChanged(WallpaperColors colors, int which) {
|
||||
listener.onColorsChanged(convertColorsObject(colors), which);
|
||||
}
|
||||
};
|
||||
mWm.addOnColorsChangedListener(onChangeListener, null);
|
||||
}
|
||||
|
||||
private WallpaperColorsCompat convertColorsObject(WallpaperColors colors) {
|
||||
if (colors == null) {
|
||||
return null;
|
||||
}
|
||||
Color primary = colors.getPrimaryColor();
|
||||
Color secondary = colors.getSecondaryColor();
|
||||
Color tertiary = colors.getTertiaryColor();
|
||||
int primaryVal = primary != null ? primary.toArgb() : 0;
|
||||
int secondaryVal = secondary != null ? secondary.toArgb() : 0;
|
||||
int tertiaryVal = tertiary != null ? tertiary.toArgb() : 0;
|
||||
int colorHints = 0;
|
||||
try {
|
||||
if (mWCColorHintsMethod != null) {
|
||||
colorHints = (Integer) mWCColorHintsMethod.invoke(colors);
|
||||
}
|
||||
} catch (Exception exc) {
|
||||
Log.e(TAG, "error calling color hints", exc);
|
||||
}
|
||||
return new WallpaperColorsCompat(primaryVal, secondaryVal, tertiaryVal, colorHints);
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue