Merge "Partially move wallpaper local color extraction to background" into tm-qpr-dev

This commit is contained in:
Aurélien Pomini
2023-03-22 11:43:14 +00:00
committed by Android (Google) Code Review

View File

@@ -61,6 +61,7 @@ import android.hardware.display.DisplayManager.DisplayListener;
import android.os.Build; import android.os.Build;
import android.os.Bundle; import android.os.Bundle;
import android.os.Handler; import android.os.Handler;
import android.os.HandlerThread;
import android.os.IBinder; import android.os.IBinder;
import android.os.Looper; import android.os.Looper;
import android.os.Message; import android.os.Message;
@@ -96,6 +97,7 @@ import android.view.WindowManager;
import android.view.WindowManagerGlobal; import android.view.WindowManagerGlobal;
import android.window.ClientWindowFrames; import android.window.ClientWindowFrames;
import com.android.internal.annotations.GuardedBy;
import com.android.internal.annotations.VisibleForTesting; import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.os.HandlerCaller; import com.android.internal.os.HandlerCaller;
import com.android.internal.view.BaseIWindow; import com.android.internal.view.BaseIWindow;
@@ -104,9 +106,10 @@ import com.android.internal.view.BaseSurfaceHolder;
import java.io.FileDescriptor; import java.io.FileDescriptor;
import java.io.PrintWriter; import java.io.PrintWriter;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays; import java.util.HashSet;
import java.util.List; import java.util.List;
import java.util.Objects; import java.util.Objects;
import java.util.Set;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicBoolean;
import java.util.function.Supplier; import java.util.function.Supplier;
@@ -166,11 +169,12 @@ public abstract class WallpaperService extends Service {
private static final int MSG_RESIZE_PREVIEW = 10110; private static final int MSG_RESIZE_PREVIEW = 10110;
private static final int MSG_REPORT_SHOWN = 10150; private static final int MSG_REPORT_SHOWN = 10150;
private static final int MSG_UPDATE_DIMMING = 10200; private static final int MSG_UPDATE_DIMMING = 10200;
private static final List<Float> PROHIBITED_STEPS = Arrays.asList(0f, Float.POSITIVE_INFINITY,
Float.NEGATIVE_INFINITY);
/** limit calls to {@link Engine#onComputeColors} to at most once per second */
private static final int NOTIFY_COLORS_RATE_LIMIT_MS = 1000; private static final int NOTIFY_COLORS_RATE_LIMIT_MS = 1000;
private static final int PROCESS_LOCAL_COLORS_INTERVAL_MS = 1000;
/** limit calls to {@link Engine#processLocalColorsInternal} to at most once per 2 seconds */
private static final int PROCESS_LOCAL_COLORS_INTERVAL_MS = 2000;
private static final boolean ENABLE_WALLPAPER_DIMMING = private static final boolean ENABLE_WALLPAPER_DIMMING =
SystemProperties.getBoolean("persist.debug.enable_wallpaper_dimming", true); SystemProperties.getBoolean("persist.debug.enable_wallpaper_dimming", true);
@@ -180,6 +184,9 @@ public abstract class WallpaperService extends Service {
private final ArrayList<Engine> mActiveEngines private final ArrayList<Engine> mActiveEngines
= new ArrayList<Engine>(); = new ArrayList<Engine>();
private Handler mBackgroundHandler;
private HandlerThread mBackgroundThread;
static final class WallpaperCommand { static final class WallpaperCommand {
String action; String action;
int x; int x;
@@ -198,14 +205,6 @@ public abstract class WallpaperService extends Service {
*/ */
public class Engine { public class Engine {
IWallpaperEngineWrapper mIWallpaperEngine; IWallpaperEngineWrapper mIWallpaperEngine;
final ArraySet<RectF> mLocalColorAreas = new ArraySet<>(4);
final ArraySet<RectF> mLocalColorsToAdd = new ArraySet<>(4);
// 2D matrix [x][y] to represent a page of a portion of a window
EngineWindowPage[] mWindowPages = new EngineWindowPage[0];
Bitmap mLastScreenshot;
int mLastWindowPage = -1;
private boolean mResetWindowPages;
// Copies from mIWallpaperEngine. // Copies from mIWallpaperEngine.
HandlerCaller mCaller; HandlerCaller mCaller;
@@ -267,11 +266,34 @@ public abstract class WallpaperService extends Service {
final Object mLock = new Object(); final Object mLock = new Object();
boolean mOffsetMessageEnqueued; boolean mOffsetMessageEnqueued;
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023) @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
float mPendingXOffset; @GuardedBy("mLock")
float mPendingYOffset; private float mPendingXOffset;
float mPendingXOffsetStep; @GuardedBy("mLock")
float mPendingYOffsetStep; private float mPendingYOffset;
@GuardedBy("mLock")
private float mPendingXOffsetStep;
@GuardedBy("mLock")
private float mPendingYOffsetStep;
/**
* local color extraction related fields. When a user calls `addLocalColorAreas`
*/
@GuardedBy("mLock")
private final ArraySet<RectF> mLocalColorAreas = new ArraySet<>(4);
@GuardedBy("mLock")
private final ArraySet<RectF> mLocalColorsToAdd = new ArraySet<>(4);
private long mLastProcessLocalColorsTimestamp;
private AtomicBoolean mProcessLocalColorsPending = new AtomicBoolean(false);
private int mPixelCopyCount = 0;
// 2D matrix [x][y] to represent a page of a portion of a window
@GuardedBy("mLock")
private EngineWindowPage[] mWindowPages = new EngineWindowPage[0];
private Bitmap mLastScreenshot;
private boolean mResetWindowPages;
boolean mPendingSync; boolean mPendingSync;
MotionEvent mPendingMove; MotionEvent mPendingMove;
boolean mIsInAmbientMode; boolean mIsInAmbientMode;
@@ -280,12 +302,8 @@ public abstract class WallpaperService extends Service {
private long mLastColorInvalidation; private long mLastColorInvalidation;
private final Runnable mNotifyColorsChanged = this::notifyColorsChanged; private final Runnable mNotifyColorsChanged = this::notifyColorsChanged;
// used to throttle processLocalColors
private long mLastProcessLocalColorsTimestamp;
private AtomicBoolean mProcessLocalColorsPending = new AtomicBoolean(false);
private final Supplier<Long> mClockFunction; private final Supplier<Long> mClockFunction;
private final Handler mHandler; private final Handler mHandler;
private Display mDisplay; private Display mDisplay;
private Context mDisplayContext; private Context mDisplayContext;
private int mDisplayState; private int mDisplayState;
@@ -825,7 +843,7 @@ public abstract class WallpaperService extends Service {
+ "was not established."); + "was not established.");
} }
mResetWindowPages = true; mResetWindowPages = true;
processLocalColors(mPendingXOffset, mPendingXOffsetStep); processLocalColors();
} catch (RemoteException e) { } catch (RemoteException e) {
Log.w(TAG, "Can't notify system because wallpaper connection was lost.", e); Log.w(TAG, "Can't notify system because wallpaper connection was lost.", e);
} }
@@ -1361,10 +1379,9 @@ public abstract class WallpaperService extends Service {
mIsCreating = false; mIsCreating = false;
mSurfaceCreated = true; mSurfaceCreated = true;
if (redrawNeeded) { if (redrawNeeded) {
resetWindowPages();
mSession.finishDrawing(mWindow, null /* postDrawTransaction */, mSession.finishDrawing(mWindow, null /* postDrawTransaction */,
Integer.MAX_VALUE); Integer.MAX_VALUE);
processLocalColors(mPendingXOffset, mPendingXOffsetStep); processLocalColors();
} }
reposition(); reposition();
reportEngineShown(shouldWaitForEngineShown()); reportEngineShown(shouldWaitForEngineShown());
@@ -1509,7 +1526,7 @@ public abstract class WallpaperService extends Service {
if (!mDestroyed) { if (!mDestroyed) {
mVisible = visible; mVisible = visible;
reportVisibility(); reportVisibility();
if (mReportedVisible) processLocalColors(mPendingXOffset, mPendingXOffsetStep); if (mReportedVisible) processLocalColors();
} else { } else {
AnimationHandler.requestAnimatorsEnabled(visible, this); AnimationHandler.requestAnimatorsEnabled(visible, this);
} }
@@ -1594,14 +1611,14 @@ public abstract class WallpaperService extends Service {
} }
// setup local color extraction data // setup local color extraction data
processLocalColors(xOffset, xOffsetStep); processLocalColors();
} }
/** /**
* Thread-safe util to call {@link #processLocalColorsInternal} with a minimum interval of * Thread-safe util to call {@link #processLocalColorsInternal} with a minimum interval of
* {@link #PROCESS_LOCAL_COLORS_INTERVAL_MS} between two calls. * {@link #PROCESS_LOCAL_COLORS_INTERVAL_MS} between two calls.
*/ */
private void processLocalColors(float xOffset, float xOffsetStep) { private void processLocalColors() {
if (mProcessLocalColorsPending.compareAndSet(false, true)) { if (mProcessLocalColorsPending.compareAndSet(false, true)) {
final long now = mClockFunction.get(); final long now = mClockFunction.get();
final long timeSinceLastColorProcess = now - mLastProcessLocalColorsTimestamp; final long timeSinceLastColorProcess = now - mLastProcessLocalColorsTimestamp;
@@ -1611,80 +1628,98 @@ public abstract class WallpaperService extends Service {
mHandler.postDelayed(() -> { mHandler.postDelayed(() -> {
mLastProcessLocalColorsTimestamp = now + timeToWait; mLastProcessLocalColorsTimestamp = now + timeToWait;
mProcessLocalColorsPending.set(false); mProcessLocalColorsPending.set(false);
processLocalColorsInternal(xOffset, xOffsetStep); processLocalColorsInternal();
}, timeToWait); }, timeToWait);
} }
} }
private void processLocalColorsInternal(float xOffset, float xOffsetStep) { /**
// implemented by the wallpaper * Default implementation of the local color extraction.
* This will take a screenshot of the whole wallpaper on the main thread.
* Then, in a background thread, for each launcher page, for each area that needs color
* extraction in this page, creates a sub-bitmap and call {@link WallpaperColors#fromBitmap}
* to extract the colors. Every time a launcher page has been processed, call
* {@link #notifyLocalColorsChanged} with the color and areas of this page.
*/
private void processLocalColorsInternal() {
if (supportsLocalColorExtraction()) return; if (supportsLocalColorExtraction()) return;
if (DEBUG) { float xOffset;
Log.d(TAG, "processLocalColors " + xOffset + " of step " float xOffsetStep;
+ xOffsetStep); float wallpaperDimAmount;
} int xPage;
//below is the default implementation
if (xOffset % xOffsetStep > MIN_PAGE_ALLOWED_MARGIN
|| !mSurfaceHolder.getSurface().isValid()) return;
int xCurrentPage;
int xPages; int xPages;
if (!validStep(xOffsetStep)) { Set<RectF> areas;
if (DEBUG) {
Log.w(TAG, "invalid offset step " + xOffsetStep);
}
xOffset = 0;
xOffsetStep = 1;
xCurrentPage = 0;
xPages = 1;
} else {
xPages = Math.round(1 / xOffsetStep) + 1;
xOffsetStep = (float) 1 / (float) xPages;
float shrink = (float) (xPages - 1) / (float) xPages;
xOffset *= shrink;
xCurrentPage = Math.round(xOffset / xOffsetStep);
}
if (DEBUG) {
Log.d(TAG, "xPages " + xPages + " xPage " + xCurrentPage);
Log.d(TAG, "xOffsetStep " + xOffsetStep + " xOffset " + xOffset);
}
float finalXOffsetStep = xOffsetStep;
float finalXOffset = xOffset;
Trace.beginSection("WallpaperService#processLocalColors");
resetWindowPages();
int xPage = xCurrentPage;
EngineWindowPage current; EngineWindowPage current;
if (mWindowPages.length == 0 || (mWindowPages.length != xPages)) {
mWindowPages = new EngineWindowPage[xPages]; synchronized (mLock) {
initWindowPages(mWindowPages, finalXOffsetStep); xOffset = mPendingXOffset;
} xOffsetStep = mPendingXOffsetStep;
if (mLocalColorsToAdd.size() != 0) { wallpaperDimAmount = mWallpaperDimAmount;
for (RectF colorArea : mLocalColorsToAdd) {
if (!isValid(colorArea)) continue;
mLocalColorAreas.add(colorArea);
int colorPage = getRectFPage(colorArea, finalXOffsetStep);
EngineWindowPage currentPage = mWindowPages[colorPage];
currentPage.setLastUpdateTime(0);
currentPage.removeColor(colorArea);
}
mLocalColorsToAdd.clear();
}
if (xPage >= mWindowPages.length) {
if (DEBUG) { if (DEBUG) {
Log.e(TAG, "error xPage >= mWindowPages.length page: " + xPage); Log.d(TAG, "processLocalColors " + xOffset + " of step "
Log.e(TAG, "error on page " + xPage + " out of " + xPages); + xOffsetStep);
Log.e(TAG,
"error on xOffsetStep " + finalXOffsetStep
+ " xOffset " + finalXOffset);
} }
xPage = mWindowPages.length - 1; if (xOffset % xOffsetStep > MIN_PAGE_ALLOWED_MARGIN
|| !mSurfaceHolder.getSurface().isValid()) return;
int xCurrentPage;
if (!validStep(xOffsetStep)) {
if (DEBUG) {
Log.w(TAG, "invalid offset step " + xOffsetStep);
}
xOffset = 0;
xOffsetStep = 1;
xCurrentPage = 0;
xPages = 1;
} else {
xPages = Math.round(1 / xOffsetStep) + 1;
xOffsetStep = (float) 1 / (float) xPages;
float shrink = (float) (xPages - 1) / (float) xPages;
xOffset *= shrink;
xCurrentPage = Math.round(xOffset / xOffsetStep);
}
if (DEBUG) {
Log.d(TAG, "xPages " + xPages + " xPage " + xCurrentPage);
Log.d(TAG, "xOffsetStep " + xOffsetStep + " xOffset " + xOffset);
}
float finalXOffsetStep = xOffsetStep;
float finalXOffset = xOffset;
resetWindowPages();
xPage = xCurrentPage;
if (mWindowPages.length == 0 || (mWindowPages.length != xPages)) {
mWindowPages = new EngineWindowPage[xPages];
initWindowPages(mWindowPages, finalXOffsetStep);
}
if (mLocalColorsToAdd.size() != 0) {
for (RectF colorArea : mLocalColorsToAdd) {
if (!isValid(colorArea)) continue;
mLocalColorAreas.add(colorArea);
int colorPage = getRectFPage(colorArea, finalXOffsetStep);
EngineWindowPage currentPage = mWindowPages[colorPage];
currentPage.setLastUpdateTime(0);
currentPage.removeColor(colorArea);
}
mLocalColorsToAdd.clear();
}
if (xPage >= mWindowPages.length) {
if (DEBUG) {
Log.e(TAG, "error xPage >= mWindowPages.length page: " + xPage);
Log.e(TAG, "error on page " + xPage + " out of " + xPages);
Log.e(TAG,
"error on xOffsetStep " + finalXOffsetStep
+ " xOffset " + finalXOffset);
}
xPage = mWindowPages.length - 1;
}
current = mWindowPages[xPage];
areas = new HashSet<>(current.getAreas());
} }
current = mWindowPages[xPage]; updatePage(current, areas, xPage, xPages, wallpaperDimAmount);
updatePage(current, xPage, xPages, finalXOffsetStep);
Trace.endSection();
} }
@GuardedBy("mLock")
private void initWindowPages(EngineWindowPage[] windowPages, float step) { private void initWindowPages(EngineWindowPage[] windowPages, float step) {
for (int i = 0; i < windowPages.length; i++) { for (int i = 0; i < windowPages.length; i++) {
windowPages[i] = new EngineWindowPage(); windowPages[i] = new EngineWindowPage();
@@ -1701,16 +1736,16 @@ public abstract class WallpaperService extends Service {
} }
} }
void updatePage(EngineWindowPage currentPage, int pageIndx, int numPages, void updatePage(EngineWindowPage currentPage, Set<RectF> areas, int pageIndx, int numPages,
float xOffsetStep) { float wallpaperDimAmount) {
// in case the clock is zero, we start with negative time // in case the clock is zero, we start with negative time
long current = SystemClock.elapsedRealtime() - DEFAULT_UPDATE_SCREENSHOT_DURATION; long current = SystemClock.elapsedRealtime() - DEFAULT_UPDATE_SCREENSHOT_DURATION;
long lapsed = current - currentPage.getLastUpdateTime(); long lapsed = current - currentPage.getLastUpdateTime();
// Always update the page when the last update time is <= 0 // Always update the page when the last update time is <= 0
// This is important especially when the device first boots // This is important especially when the device first boots
if (lapsed < DEFAULT_UPDATE_SCREENSHOT_DURATION) { if (lapsed < DEFAULT_UPDATE_SCREENSHOT_DURATION) return;
return;
}
Surface surface = mSurfaceHolder.getSurface(); Surface surface = mSurfaceHolder.getSurface();
if (!surface.isValid()) return; if (!surface.isValid()) return;
boolean widthIsLarger = mSurfaceSize.x > mSurfaceSize.y; boolean widthIsLarger = mSurfaceSize.x > mSurfaceSize.y;
@@ -1723,43 +1758,59 @@ public abstract class WallpaperService extends Service {
Log.e(TAG, "wrong width and height values of bitmap " + width + " " + height); Log.e(TAG, "wrong width and height values of bitmap " + width + " " + height);
return; return;
} }
final String pixelCopySectionName = "WallpaperService#pixelCopy";
final int pixelCopyCount = mPixelCopyCount++;
Trace.beginAsyncSection(pixelCopySectionName, pixelCopyCount);
Bitmap screenShot = Bitmap.createBitmap(width, height, Bitmap screenShot = Bitmap.createBitmap(width, height,
Bitmap.Config.ARGB_8888); Bitmap.Config.ARGB_8888);
final Bitmap finalScreenShot = screenShot; final Bitmap finalScreenShot = screenShot;
Trace.beginSection("WallpaperService#pixelCopy"); try {
PixelCopy.request(surface, screenShot, (res) -> { // TODO(b/274427458) check if this can be done in the background.
Trace.endSection(); PixelCopy.request(surface, screenShot, (res) -> {
if (DEBUG) Log.d(TAG, "result of pixel copy is " + res); Trace.endAsyncSection(pixelCopySectionName, pixelCopyCount);
if (res != PixelCopy.SUCCESS) { if (DEBUG) {
Bitmap lastBitmap = currentPage.getBitmap(); Log.d(TAG, "result of pixel copy is: "
// assign the last bitmap taken for now + (res == PixelCopy.SUCCESS ? "SUCCESS" : "FAILURE"));
currentPage.setBitmap(mLastScreenshot);
Bitmap lastScreenshot = mLastScreenshot;
if (lastScreenshot != null && !lastScreenshot.isRecycled()
&& !Objects.equals(lastBitmap, lastScreenshot)) {
updatePageColors(currentPage, pageIndx, numPages, xOffsetStep);
} }
} else { if (res != PixelCopy.SUCCESS) {
mLastScreenshot = finalScreenShot; Bitmap lastBitmap = currentPage.getBitmap();
// going to hold this lock for a while // assign the last bitmap taken for now
currentPage.setBitmap(finalScreenShot); currentPage.setBitmap(mLastScreenshot);
currentPage.setLastUpdateTime(current); Bitmap lastScreenshot = mLastScreenshot;
updatePageColors(currentPage, pageIndx, numPages, xOffsetStep); if (lastScreenshot != null && !Objects.equals(lastBitmap, lastScreenshot)) {
} updatePageColors(
}, mHandler); currentPage, areas, pageIndx, numPages, wallpaperDimAmount);
}
} else {
mLastScreenshot = finalScreenShot;
currentPage.setBitmap(finalScreenShot);
currentPage.setLastUpdateTime(current);
updatePageColors(
currentPage, areas, pageIndx, numPages, wallpaperDimAmount);
}
}, mBackgroundHandler);
} catch (IllegalArgumentException e) {
// this can potentially happen if the surface is invalidated right between the
// surface.isValid() check and the PixelCopy operation.
// in this case, stop: we'll compute colors on the next processLocalColors call.
Log.w(TAG, "Cancelling processLocalColors: exception caught during PixelCopy");
}
} }
// locked by the passed page // locked by the passed page
private void updatePageColors(EngineWindowPage page, int pageIndx, int numPages, private void updatePageColors(EngineWindowPage page, Set<RectF> areas,
float xOffsetStep) { int pageIndx, int numPages, float wallpaperDimAmount) {
if (page.getBitmap() == null) return; if (page.getBitmap() == null) return;
if (!mBackgroundHandler.getLooper().isCurrentThread()) {
throw new IllegalStateException(
"ProcessLocalColors should be called from the background thread");
}
Trace.beginSection("WallpaperService#updatePageColors"); Trace.beginSection("WallpaperService#updatePageColors");
if (DEBUG) { if (DEBUG) {
Log.d(TAG, "updatePageColorsLocked for page " + pageIndx + " with areas " Log.d(TAG, "updatePageColorsLocked for page " + pageIndx + " with areas "
+ page.getAreas().size() + " and bitmap size of " + page.getAreas().size() + " and bitmap size of "
+ page.getBitmap().getWidth() + " x " + page.getBitmap().getHeight()); + page.getBitmap().getWidth() + " x " + page.getBitmap().getHeight());
} }
for (RectF area: page.getAreas()) { for (RectF area: areas) {
if (area == null) continue; if (area == null) continue;
RectF subArea = generateSubRect(area, pageIndx, numPages); RectF subArea = generateSubRect(area, pageIndx, numPages);
Bitmap b = page.getBitmap(); Bitmap b = page.getBitmap();
@@ -1769,12 +1820,12 @@ public abstract class WallpaperService extends Service {
int height = Math.round(b.getHeight() * subArea.height()); int height = Math.round(b.getHeight() * subArea.height());
Bitmap target; Bitmap target;
try { try {
target = Bitmap.createBitmap(page.getBitmap(), x, y, width, height); target = Bitmap.createBitmap(b, x, y, width, height);
} catch (Exception e) { } catch (Exception e) {
Log.e(TAG, "Error creating page local color bitmap", e); Log.e(TAG, "Error creating page local color bitmap", e);
continue; continue;
} }
WallpaperColors color = WallpaperColors.fromBitmap(target, mWallpaperDimAmount); WallpaperColors color = WallpaperColors.fromBitmap(target, wallpaperDimAmount);
target.recycle(); target.recycle();
WallpaperColors currentColor = page.getColors(area); WallpaperColors currentColor = page.getColors(area);
@@ -1791,12 +1842,14 @@ public abstract class WallpaperService extends Service {
+ " local color callback for area" + area + " for page " + pageIndx + " local color callback for area" + area + " for page " + pageIndx
+ " of " + numPages); + " of " + numPages);
} }
try { mHandler.post(() -> {
mConnection.onLocalWallpaperColorsChanged(area, color, try {
mDisplayContext.getDisplayId()); mConnection.onLocalWallpaperColorsChanged(area, color,
} catch (RemoteException e) { mDisplayContext.getDisplayId());
Log.e(TAG, "Error calling Connection.onLocalWallpaperColorsChanged", e); } catch (RemoteException e) {
} Log.e(TAG, "Error calling Connection.onLocalWallpaperColorsChanged", e);
}
});
} }
} }
Trace.endSection(); Trace.endSection();
@@ -1822,16 +1875,17 @@ public abstract class WallpaperService extends Service {
return new RectF(left, in.top, right, in.bottom); return new RectF(left, in.top, right, in.bottom);
} }
@GuardedBy("mLock")
private void resetWindowPages() { private void resetWindowPages() {
if (supportsLocalColorExtraction()) return; if (supportsLocalColorExtraction()) return;
if (!mResetWindowPages) return; if (!mResetWindowPages) return;
mResetWindowPages = false; mResetWindowPages = false;
mLastWindowPage = -1;
for (int i = 0; i < mWindowPages.length; i++) { for (int i = 0; i < mWindowPages.length; i++) {
mWindowPages[i].setLastUpdateTime(0L); mWindowPages[i].setLastUpdateTime(0L);
} }
} }
@GuardedBy("mLock")
private int getRectFPage(RectF area, float step) { private int getRectFPage(RectF area, float step) {
if (!isValid(area)) return 0; if (!isValid(area)) return 0;
if (!validStep(step)) return 0; if (!validStep(step)) return 0;
@@ -1852,12 +1906,12 @@ public abstract class WallpaperService extends Service {
if (DEBUG) { if (DEBUG) {
Log.d(TAG, "addLocalColorsAreas adding local color areas " + regions); Log.d(TAG, "addLocalColorsAreas adding local color areas " + regions);
} }
mHandler.post(() -> { mBackgroundHandler.post(() -> {
mLocalColorsToAdd.addAll(regions); synchronized (mLock) {
processLocalColors(mPendingXOffset, mPendingYOffset); mLocalColorsToAdd.addAll(regions);
}
processLocalColors();
}); });
} }
/** /**
@@ -1867,16 +1921,18 @@ public abstract class WallpaperService extends Service {
*/ */
public void removeLocalColorsAreas(@NonNull List<RectF> regions) { public void removeLocalColorsAreas(@NonNull List<RectF> regions) {
if (supportsLocalColorExtraction()) return; if (supportsLocalColorExtraction()) return;
mHandler.post(() -> { mBackgroundHandler.post(() -> {
float step = mPendingXOffsetStep; synchronized (mLock) {
mLocalColorsToAdd.removeAll(regions); float step = mPendingXOffsetStep;
mLocalColorAreas.removeAll(regions); mLocalColorsToAdd.removeAll(regions);
if (!validStep(step)) { mLocalColorAreas.removeAll(regions);
return; if (!validStep(step)) {
} return;
for (int i = 0; i < mWindowPages.length; i++) { }
for (int j = 0; j < regions.size(); j++) { for (int i = 0; i < mWindowPages.length; i++) {
mWindowPages[i].removeArea(regions.get(j)); for (int j = 0; j < regions.size(); j++) {
mWindowPages[i].removeArea(regions.get(j));
}
} }
} }
}); });
@@ -1894,7 +1950,7 @@ public abstract class WallpaperService extends Service {
} }
private boolean validStep(float step) { private boolean validStep(float step) {
return !PROHIBITED_STEPS.contains(step) && step > 0. && step <= 1.; return !Float.isNaN(step) && step > 0f && step <= 1f;
} }
void doCommand(WallpaperCommand cmd) { void doCommand(WallpaperCommand cmd) {
@@ -2498,6 +2554,9 @@ public abstract class WallpaperService extends Service {
@Override @Override
public void onCreate() { public void onCreate() {
Trace.beginSection("WPMS.onCreate"); Trace.beginSection("WPMS.onCreate");
mBackgroundThread = new HandlerThread("DefaultWallpaperLocalColorExtractor");
mBackgroundThread.start();
mBackgroundHandler = new Handler(mBackgroundThread.getLooper());
super.onCreate(); super.onCreate();
Trace.endSection(); Trace.endSection();
} }
@@ -2510,6 +2569,7 @@ public abstract class WallpaperService extends Service {
mActiveEngines.get(i).detach(); mActiveEngines.get(i).detach();
} }
mActiveEngines.clear(); mActiveEngines.clear();
mBackgroundThread.quitSafely();
Trace.endSection(); Trace.endSection();
} }