From ab83773e211daf43b6b3ab327be2e94bf61663b3 Mon Sep 17 00:00:00 2001 From: Sunny Goyal Date: Tue, 27 Mar 2018 17:35:54 -0700 Subject: [PATCH] Updating fallback activity > Wallpaper based theme support > Light/dark system UI > Swipe gestures to start and dismiss a task > Fixing insets and task preview size Bug: 75979063 Change-Id: Id402e6ac50551a7c0849742e3a0e77df3ead5aa2 --- quickstep/AndroidManifest.xml | 11 +++++- .../res/layout/fallback_recents_activity.xml | 9 +++-- .../uioverrides/TaskViewTouchController.java | 34 ++++++++--------- .../launcher3/uioverrides/UiFactory.java | 19 ++++++++-- .../quickstep/ActivityControlHelper.java | 1 + .../quickstep/FallbackActivityOptions.java | 15 +++++++- .../android/quickstep/RecentsActivity.java | 8 ++++ .../{ => fallback}/FallbackRecentsView.java | 10 ++--- .../{ => fallback}/RecentsRootView.java | 15 ++++++-- .../fallback/RecentsTaskController.java | 31 +++++++++++++++ .../android/quickstep/views/RecentsView.java | 2 +- .../launcher3/BaseDraggingActivity.java | 38 ++++++++++++++++++- src/com/android/launcher3/Launcher.java | 22 +---------- .../dynamicui/WallpaperColorInfo.java | 33 ++++++---------- 14 files changed, 168 insertions(+), 80 deletions(-) rename quickstep/src/com/android/quickstep/{ => fallback}/FallbackRecentsView.java (88%) rename quickstep/src/com/android/quickstep/{ => fallback}/RecentsRootView.java (79%) create mode 100644 quickstep/src/com/android/quickstep/fallback/RecentsTaskController.java diff --git a/quickstep/AndroidManifest.xml b/quickstep/AndroidManifest.xml index 8b28597dd1..f62d1d6ed5 100644 --- a/quickstep/AndroidManifest.xml +++ b/quickstep/AndroidManifest.xml @@ -48,7 +48,16 @@ It is set to true so that the activity can be started from command line --> + android:excludeFromRecents="true" + android:launchMode="singleTask" + android:clearTaskOnLaunch="true" + android:stateNotNeeded="true" + android:theme="@style/LauncherTheme" + android:screenOrientation="unspecified" + android:configChanges="keyboard|keyboardHidden|navigation|orientation|screenSize|screenLayout|smallestScreenSize" + android:resizeableActivity="true" + android:resumeWhilePausing="true" + android:taskAffinity="" /> - + android:layout_height="match_parent" + android:fitsSystemWindows="true"> - - \ No newline at end of file + \ No newline at end of file diff --git a/quickstep/src/com/android/launcher3/uioverrides/TaskViewTouchController.java b/quickstep/src/com/android/launcher3/uioverrides/TaskViewTouchController.java index 369ae3ab6c..7b2487ada8 100644 --- a/quickstep/src/com/android/launcher3/uioverrides/TaskViewTouchController.java +++ b/quickstep/src/com/android/launcher3/uioverrides/TaskViewTouchController.java @@ -15,7 +15,6 @@ */ package com.android.launcher3.uioverrides; -import static com.android.launcher3.LauncherState.OVERVIEW; import static com.android.launcher3.anim.Interpolators.scrollInterpolatorForVelocity; import android.animation.Animator; @@ -26,15 +25,15 @@ import android.view.MotionEvent; import android.view.View; import com.android.launcher3.AbstractFloatingView; -import com.android.launcher3.Launcher; +import com.android.launcher3.BaseDraggingActivity; import com.android.launcher3.Utilities; import com.android.launcher3.anim.AnimatorPlaybackController; import com.android.launcher3.anim.Interpolators; -import com.android.launcher3.dragndrop.DragLayer; import com.android.launcher3.touch.SwipeDetector; import com.android.launcher3.userevent.nano.LauncherLogProto.Action.Direction; import com.android.launcher3.userevent.nano.LauncherLogProto.Action.Touch; import com.android.launcher3.util.TouchController; +import com.android.launcher3.views.BaseDragLayer; import com.android.quickstep.PendingAnimation; import com.android.quickstep.views.RecentsView; import com.android.quickstep.views.TaskView; @@ -42,8 +41,8 @@ import com.android.quickstep.views.TaskView; /** * Touch controller for handling task view card swipes */ -public class TaskViewTouchController extends AnimatorListenerAdapter - implements TouchController, SwipeDetector.Listener { +public abstract class TaskViewTouchController + extends AnimatorListenerAdapter implements TouchController, SwipeDetector.Listener { private static final String TAG = "OverviewSwipeController"; @@ -53,7 +52,7 @@ public class TaskViewTouchController extends AnimatorListenerAdapter // Progress after which the transition is assumed to be a success in case user does not fling private static final float SUCCESS_TRANSITION_PROGRESS = 0.5f; - private final Launcher mLauncher; + protected final T mActivity; private final SwipeDetector mDetector; private final RecentsView mRecentsView; private final int[] mTempCords = new int[2]; @@ -70,10 +69,10 @@ public class TaskViewTouchController extends AnimatorListenerAdapter private TaskView mTaskBeingDragged; - public TaskViewTouchController(Launcher launcher) { - mLauncher = launcher; - mRecentsView = launcher.getOverviewPanel(); - mDetector = new SwipeDetector(launcher, this, SwipeDetector.VERTICAL); + public TaskViewTouchController(T activity) { + mActivity = activity; + mRecentsView = activity.getOverviewPanel(); + mDetector = new SwipeDetector(activity, this, SwipeDetector.VERTICAL); } private boolean canInterceptTouch() { @@ -81,12 +80,14 @@ public class TaskViewTouchController extends AnimatorListenerAdapter // If we are already animating from a previous state, we can intercept. return true; } - if (AbstractFloatingView.getTopOpenView(mLauncher) != null) { + if (AbstractFloatingView.getTopOpenView(mActivity) != null) { return false; } - return mLauncher.isInState(OVERVIEW); + return isRecentsInteractive(); } + protected abstract boolean isRecentsInteractive(); + @Override public void onAnimationCancel(Animator animation) { if (mCurrentAnimation != null && animation == mCurrentAnimation.getTarget()) { @@ -115,7 +116,7 @@ public class TaskViewTouchController extends AnimatorListenerAdapter mTaskBeingDragged = null; View view = mRecentsView.getChildAt(mRecentsView.getCurrentPage()); - if (view instanceof TaskView && mLauncher.getDragLayer().isEventOverView(view, ev)) { + if (view instanceof TaskView && mActivity.getDragLayer().isEventOverView(view, ev)) { // The tile can be dragged down to open the task. mTaskBeingDragged = (TaskView) view; directionsToDetectScroll = SwipeDetector.DIRECTION_BOTH; @@ -156,9 +157,8 @@ public class TaskViewTouchController extends AnimatorListenerAdapter } mCurrentAnimationIsGoingUp = goingUp; - float range = mLauncher.getAllAppsController().getShiftRange(); - long maxDuration = (long) (2 * range); - DragLayer dl = mLauncher.getDragLayer(); + BaseDragLayer dl = mActivity.getDragLayer(); + long maxDuration = (long) (2 * dl.getHeight()); if (goingUp) { mPendingAnimation = mRecentsView.createTaskDismissAnimation(mTaskBeingDragged, @@ -254,7 +254,7 @@ public class TaskViewTouchController extends AnimatorListenerAdapter } if (wasSuccess) { if (!mCurrentAnimationIsGoingUp) { - mLauncher.getUserEventDispatcher().logTaskLaunch(logAction, + mActivity.getUserEventDispatcher().logTaskLaunch(logAction, Direction.DOWN, mTaskBeingDragged.getTask().getTopComponent()); } } diff --git a/quickstep/src/com/android/launcher3/uioverrides/UiFactory.java b/quickstep/src/com/android/launcher3/uioverrides/UiFactory.java index e6d06da5e7..3cae3718f3 100644 --- a/quickstep/src/com/android/launcher3/uioverrides/UiFactory.java +++ b/quickstep/src/com/android/launcher3/uioverrides/UiFactory.java @@ -16,6 +16,7 @@ package com.android.launcher3.uioverrides; +import static com.android.launcher3.LauncherState.OVERVIEW; import static com.android.launcher3.Utilities.getPrefs; import static com.android.quickstep.OverviewInteractionState.KEY_SWIPE_UP_ENABLED; import static com.android.launcher3.LauncherState.ALL_APPS; @@ -41,19 +42,19 @@ public class UiFactory { return new TouchController[] { launcher.getDragController(), new LandscapeStatesTouchController(launcher), - new TaskViewTouchController(launcher)}; + new LauncherTaskViewcontroller(launcher)}; } if (launcher.getDeviceProfile().isVerticalBarLayout()) { return new TouchController[] { launcher.getDragController(), new LandscapeStatesTouchController(launcher), new LandscapeEdgeSwipeController(launcher), - new TaskViewTouchController(launcher)}; + new LauncherTaskViewcontroller(launcher)}; } else { return new TouchController[] { launcher.getDragController(), new PortraitStatesTouchController(launcher), - new TaskViewTouchController(launcher)}; + new LauncherTaskViewcontroller(launcher)}; } } @@ -101,4 +102,16 @@ public class UiFactory { model.onTrimMemory(level); } } + + private static class LauncherTaskViewcontroller extends TaskViewTouchController { + + public LauncherTaskViewcontroller(Launcher activity) { + super(activity); + } + + @Override + protected boolean isRecentsInteractive() { + return mActivity.isInState(OVERVIEW); + } + } } diff --git a/quickstep/src/com/android/quickstep/ActivityControlHelper.java b/quickstep/src/com/android/quickstep/ActivityControlHelper.java index 9e2e5acf5f..4e3528c84d 100644 --- a/quickstep/src/com/android/quickstep/ActivityControlHelper.java +++ b/quickstep/src/com/android/quickstep/ActivityControlHelper.java @@ -41,6 +41,7 @@ import com.android.launcher3.LauncherState; import com.android.launcher3.allapps.AllAppsTransitionController; import com.android.launcher3.anim.AnimatorPlaybackController; import com.android.launcher3.util.ViewOnDrawExecutor; +import com.android.quickstep.fallback.FallbackRecentsView; import com.android.quickstep.views.LauncherLayoutListener; import com.android.quickstep.views.RecentsView; import com.android.quickstep.views.TaskView; diff --git a/quickstep/src/com/android/quickstep/FallbackActivityOptions.java b/quickstep/src/com/android/quickstep/FallbackActivityOptions.java index 3a7fb2db6d..04352c390b 100644 --- a/quickstep/src/com/android/quickstep/FallbackActivityOptions.java +++ b/quickstep/src/com/android/quickstep/FallbackActivityOptions.java @@ -16,13 +16,13 @@ package com.android.quickstep; import android.graphics.Rect; -import android.util.Log; import com.android.systemui.shared.recents.model.ThumbnailData; import com.android.systemui.shared.system.RecentsAnimationControllerCompat; import com.android.systemui.shared.system.RecentsAnimationListener; import com.android.systemui.shared.system.RemoteAnimationRunnerCompat; import com.android.systemui.shared.system.RemoteAnimationTargetCompat; +import com.android.systemui.shared.system.TransactionCompat; import com.android.systemui.shared.system.WindowManagerWrapper; /** @@ -39,6 +39,7 @@ public class FallbackActivityOptions implements RemoteAnimationRunnerCompat { @Override public void onAnimationStart(RemoteAnimationTargetCompat[] targetCompats, Runnable runnable) { + showOpeningTarget(targetCompats); DummyRecentsAnimationControllerCompat dummyRecentsAnim = new DummyRecentsAnimationControllerCompat(runnable); @@ -52,6 +53,18 @@ public class FallbackActivityOptions implements RemoteAnimationRunnerCompat { mListener.onAnimationCanceled(); } + private void showOpeningTarget(RemoteAnimationTargetCompat[] targetCompats) { + for (RemoteAnimationTargetCompat target : targetCompats) { + TransactionCompat t = new TransactionCompat(); + int layer = target.mode == RemoteAnimationTargetCompat.MODE_CLOSING + ? Integer.MAX_VALUE + : target.prefixOrderIndex; + t.setLayer(target.leash, layer); + t.show(target.leash); + t.apply(); + } + } + private static class DummyRecentsAnimationControllerCompat extends RecentsAnimationControllerCompat { diff --git a/quickstep/src/com/android/quickstep/RecentsActivity.java b/quickstep/src/com/android/quickstep/RecentsActivity.java index e5792056aa..cf60fdff65 100644 --- a/quickstep/src/com/android/quickstep/RecentsActivity.java +++ b/quickstep/src/com/android/quickstep/RecentsActivity.java @@ -26,7 +26,11 @@ import com.android.launcher3.LauncherAppState; import com.android.launcher3.R; import com.android.launcher3.badge.BadgeInfo; import com.android.launcher3.uioverrides.UiFactory; +import com.android.launcher3.util.SystemUiController; +import com.android.launcher3.util.Themes; import com.android.launcher3.views.BaseDragLayer; +import com.android.quickstep.fallback.FallbackRecentsView; +import com.android.quickstep.fallback.RecentsRootView; /** * A simple activity to show the recently launched tasks @@ -51,6 +55,10 @@ public class RecentsActivity extends BaseDraggingActivity { mRecentsRootView = findViewById(R.id.drag_layer); mFallbackRecentsView = findViewById(R.id.overview_panel); + mRecentsRootView.setup(); + + getSystemUiController().updateUiState(SystemUiController.UI_STATE_BASE_WINDOW, + Themes.getAttrBoolean(this, R.attr.isWorkspaceDarkText)); RecentsActivityTracker.onRecentsActivityCreate(this); } diff --git a/quickstep/src/com/android/quickstep/FallbackRecentsView.java b/quickstep/src/com/android/quickstep/fallback/FallbackRecentsView.java similarity index 88% rename from quickstep/src/com/android/quickstep/FallbackRecentsView.java rename to quickstep/src/com/android/quickstep/fallback/FallbackRecentsView.java index 251e958063..7d7f88fdb2 100644 --- a/quickstep/src/com/android/quickstep/FallbackRecentsView.java +++ b/quickstep/src/com/android/quickstep/fallback/FallbackRecentsView.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package com.android.quickstep; +package com.android.quickstep.fallback; import android.content.Context; import android.graphics.Canvas; @@ -23,6 +23,7 @@ import android.view.View; import com.android.launcher3.DeviceProfile; import com.android.launcher3.Insettable; +import com.android.quickstep.RecentsActivity; import com.android.quickstep.views.RecentsView; public class FallbackRecentsView extends RecentsView implements Insettable { @@ -73,12 +74,7 @@ public class FallbackRecentsView extends RecentsView implements public static void getCenterPageRect(DeviceProfile grid, Context context, Rect outRect) { Rect targetPadding = getPadding(grid, context); verticalCenter(targetPadding, grid); - Rect insets = grid.getInsets(); - outRect.set( - targetPadding.left + insets.left, - targetPadding.top + insets.top, - grid.widthPx - targetPadding.right - insets.right, - grid.heightPx - targetPadding.bottom - insets.bottom); + getPageRect(grid, context, outRect, targetPadding); } @Override diff --git a/quickstep/src/com/android/quickstep/RecentsRootView.java b/quickstep/src/com/android/quickstep/fallback/RecentsRootView.java similarity index 79% rename from quickstep/src/com/android/quickstep/RecentsRootView.java rename to quickstep/src/com/android/quickstep/fallback/RecentsRootView.java index 24785f9316..7aaa88c38d 100644 --- a/quickstep/src/com/android/quickstep/RecentsRootView.java +++ b/quickstep/src/com/android/quickstep/fallback/RecentsRootView.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package com.android.quickstep; +package com.android.quickstep.fallback; import android.annotation.TargetApi; import android.content.Context; @@ -25,15 +25,22 @@ 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; public class RecentsRootView extends BaseDragLayer { - private final BaseActivity mActivity; + private final RecentsActivity mActivity; public RecentsRootView(Context context, AttributeSet attrs) { super(context, attrs); - mActivity = BaseActivity.fromContext(context); - mControllers = new TouchController[0]; + mActivity = (RecentsActivity) BaseActivity.fromContext(context); + setSystemUiVisibility(SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN + | SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION + | SYSTEM_UI_FLAG_LAYOUT_STABLE); + } + + public void setup() { + mControllers = new TouchController[] { new RecentsTaskController(mActivity) }; } @TargetApi(23) diff --git a/quickstep/src/com/android/quickstep/fallback/RecentsTaskController.java b/quickstep/src/com/android/quickstep/fallback/RecentsTaskController.java new file mode 100644 index 0000000000..9463cc90f1 --- /dev/null +++ b/quickstep/src/com/android/quickstep/fallback/RecentsTaskController.java @@ -0,0 +1,31 @@ +/* + * 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.quickstep.fallback; + +import com.android.launcher3.uioverrides.TaskViewTouchController; +import com.android.quickstep.RecentsActivity; + +public class RecentsTaskController extends TaskViewTouchController { + + public RecentsTaskController(RecentsActivity activity) { + super(activity); + } + + @Override + protected boolean isRecentsInteractive() { + return mActivity.hasWindowFocus(); + } +} diff --git a/quickstep/src/com/android/quickstep/views/RecentsView.java b/quickstep/src/com/android/quickstep/views/RecentsView.java index bac8fc7461..1c4e5111ac 100644 --- a/quickstep/src/com/android/quickstep/views/RecentsView.java +++ b/quickstep/src/com/android/quickstep/views/RecentsView.java @@ -405,7 +405,7 @@ public abstract class RecentsView getPageRect(grid, context, outRect, targetPadding); } - private static void getPageRect(DeviceProfile grid, Context context, Rect outRect, + protected static void getPageRect(DeviceProfile grid, Context context, Rect outRect, Rect targetPadding) { Rect insets = grid.getInsets(); outRect.set( diff --git a/src/com/android/launcher3/BaseDraggingActivity.java b/src/com/android/launcher3/BaseDraggingActivity.java index 34819afe43..4c11fe66e0 100644 --- a/src/com/android/launcher3/BaseDraggingActivity.java +++ b/src/com/android/launcher3/BaseDraggingActivity.java @@ -34,13 +34,15 @@ import android.widget.Toast; import com.android.launcher3.LauncherSettings.Favorites; import com.android.launcher3.badge.BadgeInfo; import com.android.launcher3.compat.LauncherAppsCompat; +import com.android.launcher3.dynamicui.WallpaperColorInfo; import com.android.launcher3.shortcuts.DeepShortcutManager; import com.android.launcher3.views.BaseDragLayer; /** * Extension of BaseActivity allowing support for drag-n-drop */ -public abstract class BaseDraggingActivity extends BaseActivity { +public abstract class BaseDraggingActivity extends BaseActivity + implements WallpaperColorInfo.OnChangeListener { private static final String TAG = "BaseDraggingActivity"; @@ -57,10 +59,38 @@ public abstract class BaseDraggingActivity extends BaseActivity { private OnStartCallback mOnStartCallback; + private int mThemeRes = R.style.LauncherTheme; + @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); mIsSafeModeEnabled = getPackageManager().isSafeMode(); + + // Update theme + WallpaperColorInfo wallpaperColorInfo = WallpaperColorInfo.getInstance(this); + wallpaperColorInfo.addOnChangeListener(this); + int themeRes = getThemeRes(wallpaperColorInfo); + if (themeRes != mThemeRes) { + mThemeRes = themeRes; + setTheme(themeRes); + } + } + + @Override + public void onExtractedColorsChanged(WallpaperColorInfo wallpaperColorInfo) { + if (mThemeRes != getThemeRes(wallpaperColorInfo)) { + recreate(); + } + } + + protected int getThemeRes(WallpaperColorInfo wallpaperColorInfo) { + if (wallpaperColorInfo.isDark()) { + return R.style.LauncherThemeDark; + } else if (wallpaperColorInfo.supportsDarkText()) { + return R.style.LauncherThemeDarkText; + } else { + return R.style.LauncherTheme; + } } @Override @@ -203,6 +233,12 @@ public abstract class BaseDraggingActivity extends BaseActivity { } } + @Override + protected void onDestroy() { + super.onDestroy(); + WallpaperColorInfo.getInstance(this).removeOnChangeListener(this); + } + public void setOnStartCallback(OnStartCallback callback) { mOnStartCallback = callback; } diff --git a/src/com/android/launcher3/Launcher.java b/src/com/android/launcher3/Launcher.java index 056404e7a4..e2f748837c 100644 --- a/src/com/android/launcher3/Launcher.java +++ b/src/com/android/launcher3/Launcher.java @@ -135,8 +135,8 @@ import java.util.Set; /** * Default launcher application. */ -public class Launcher extends BaseDraggingActivity implements LauncherExterns, LauncherModel.Callbacks, - LauncherProviderChangeListener, WallpaperColorInfo.OnThemeChangeListener { +public class Launcher extends BaseDraggingActivity + implements LauncherExterns, LauncherModel.Callbacks, LauncherProviderChangeListener { public static final String TAG = "Launcher"; static final boolean LOGD = false; @@ -266,10 +266,6 @@ public class Launcher extends BaseDraggingActivity implements LauncherExterns, L } TraceHelper.beginSection("Launcher-onCreate"); - WallpaperColorInfo wallpaperColorInfo = WallpaperColorInfo.getInstance(this); - wallpaperColorInfo.setOnThemeChangeListener(this); - overrideTheme(wallpaperColorInfo.isDark(), wallpaperColorInfo.supportsDarkText()); - super.onCreate(savedInstanceState); TraceHelper.partitionSection("Launcher-onCreate", "super call"); @@ -402,23 +398,10 @@ public class Launcher extends BaseDraggingActivity implements LauncherExterns, L return mRotationHelper; } - @Override - public void onThemeChanged() { - recreate(); - } - public LauncherStateManager getStateManager() { return mStateManager; } - protected void overrideTheme(boolean isDark, boolean supportsDarkText) { - if (isDark) { - setTheme(R.style.LauncherThemeDark); - } else if (supportsDarkText) { - setTheme(R.style.LauncherThemeDarkText); - } - } - @Override public T findViewById(int id) { return mLauncherView.findViewById(id); @@ -1367,7 +1350,6 @@ public class Launcher extends BaseDraggingActivity implements LauncherExterns, L } TextKeyListener.getInstance().release(); - WallpaperColorInfo.getInstance(this).setOnThemeChangeListener(null); LauncherAnimUtils.onDestroyActivity(); diff --git a/src/com/android/launcher3/dynamicui/WallpaperColorInfo.java b/src/com/android/launcher3/dynamicui/WallpaperColorInfo.java index 267e9301a7..32605a2ebe 100644 --- a/src/com/android/launcher3/dynamicui/WallpaperColorInfo.java +++ b/src/com/android/launcher3/dynamicui/WallpaperColorInfo.java @@ -33,7 +33,8 @@ public class WallpaperColorInfo implements WallpaperManagerCompat.OnColorsChange private int mSecondaryColor; private boolean mIsDark; private boolean mSupportsDarkText; - private OnThemeChangeListener mOnThemeChangeListener; + + private OnChangeListener[] mTempListeners; private WallpaperColorInfo(Context context) { mWallpaperManager = WallpaperManagerCompat.getInstance(context); @@ -61,10 +62,8 @@ public class WallpaperColorInfo implements WallpaperManagerCompat.OnColorsChange @Override public void onColorsChanged(WallpaperColorsCompat colors, int which) { if ((which & FLAG_SYSTEM) != 0) { - boolean wasDarkTheme = mIsDark; - boolean didSupportDarkText = mSupportsDarkText; update(colors); - notifyChange(wasDarkTheme != mIsDark || didSupportDarkText != mSupportsDarkText); + notifyChange(); } } @@ -85,10 +84,6 @@ public class WallpaperColorInfo implements WallpaperManagerCompat.OnColorsChange & WallpaperColorsCompat.HINT_SUPPORTS_DARK_THEME) > 0 : false; } - public void setOnThemeChangeListener(OnThemeChangeListener onThemeChangeListener) { - this.mOnThemeChangeListener = onThemeChangeListener; - } - public void addOnChangeListener(OnChangeListener listener) { mListeners.add(listener); } @@ -97,23 +92,19 @@ public class WallpaperColorInfo implements WallpaperManagerCompat.OnColorsChange mListeners.remove(listener); } - public void notifyChange(boolean themeChanged) { - if (themeChanged) { - if (mOnThemeChangeListener != null) { - mOnThemeChangeListener.onThemeChanged(); - } - } else { - for (OnChangeListener listener : mListeners) { - listener.onExtractedColorsChanged(this); - } + 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); } - - public interface OnThemeChangeListener { - void onThemeChanged(); - } }