Loading core/java/android/service/wallpaper/WallpaperService.java +61 −105 Original line number Diff line number Diff line Loading @@ -60,7 +60,6 @@ import android.hardware.display.DisplayManager.DisplayListener; import android.os.Build; import android.os.Bundle; import android.os.Handler; import android.os.HandlerThread; import android.os.IBinder; import android.os.Looper; import android.os.Message; Loading Loading @@ -181,9 +180,6 @@ public abstract class WallpaperService extends Service { private final ArrayMap<IBinder, IWallpaperEngineWrapper> mActiveEngines = new ArrayMap<>(); private Handler mBackgroundHandler; private HandlerThread mBackgroundThread; static final class WallpaperCommand { String action; int x; Loading @@ -202,6 +198,14 @@ public abstract class WallpaperService extends Service { */ public class Engine { 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. HandlerCaller mCaller; Loading Loading @@ -262,27 +266,11 @@ public abstract class WallpaperService extends Service { final Object mLock = new Object(); boolean mOffsetMessageEnqueued; @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023) float mPendingXOffset; float mPendingYOffset; float mPendingXOffsetStep; float mPendingYOffsetStep; /** * local color extraction related fields * to be used by the background thread only (except the atomic boolean) */ final ArraySet<RectF> mLocalColorAreas = new ArraySet<>(4); 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 EngineWindowPage[] mWindowPages = new EngineWindowPage[0]; Bitmap mLastScreenshot; private boolean mResetWindowPages; boolean mPendingSync; MotionEvent mPendingMove; boolean mIsInAmbientMode; Loading @@ -291,8 +279,12 @@ public abstract class WallpaperService extends Service { private long mLastColorInvalidation; 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 Handler mHandler; private Display mDisplay; private Context mDisplayContext; private int mDisplayState; Loading Loading @@ -862,7 +854,7 @@ public abstract class WallpaperService extends Service { + "was not established."); } mResetWindowPages = true; processLocalColors(); processLocalColors(mPendingXOffset, mPendingXOffsetStep); } catch (RemoteException e) { Log.w(TAG, "Can't notify system because wallpaper connection was lost.", e); } Loading Loading @@ -1400,7 +1392,7 @@ public abstract class WallpaperService extends Service { resetWindowPages(); mSession.finishDrawing(mWindow, null /* postDrawTransaction */, Integer.MAX_VALUE); processLocalColors(); processLocalColors(mPendingXOffset, mPendingXOffsetStep); } reposition(); reportEngineShown(shouldWaitForEngineShown()); Loading Loading @@ -1544,7 +1536,7 @@ public abstract class WallpaperService extends Service { if (!mDestroyed) { mVisible = visible; reportVisibility(false); if (mReportedVisible) processLocalColors(); if (mReportedVisible) processLocalColors(mPendingXOffset, mPendingXOffsetStep); } else { AnimationHandler.requestAnimatorsEnabled(visible, this); } Loading Loading @@ -1647,41 +1639,31 @@ public abstract class WallpaperService extends Service { } // setup local color extraction data processLocalColors(); processLocalColors(xOffset, xOffsetStep); } /** * Thread-safe util to call {@link #processLocalColorsInternal} with a minimum interval of * {@link #PROCESS_LOCAL_COLORS_INTERVAL_MS} between two calls. */ private void processLocalColors() { private void processLocalColors(float xOffset, float xOffsetStep) { if (mProcessLocalColorsPending.compareAndSet(false, true)) { final long now = mClockFunction.get(); final long timeSinceLastColorProcess = now - mLastProcessLocalColorsTimestamp; final long timeToWait = Math.max(0, PROCESS_LOCAL_COLORS_INTERVAL_MS - timeSinceLastColorProcess); mBackgroundHandler.postDelayed(() -> { mHandler.postDelayed(() -> { mLastProcessLocalColorsTimestamp = now + timeToWait; mProcessLocalColorsPending.set(false); processLocalColorsInternal(); processLocalColorsInternal(xOffset, xOffsetStep); }, timeToWait); } } private void processLocalColorsInternal() { private void processLocalColorsInternal(float xOffset, float xOffsetStep) { // implemented by the wallpaper if (supportsLocalColorExtraction()) return; assertBackgroundThread(); float xOffset; float xOffsetStep; float wallpaperDimAmount; synchronized (mLock) { xOffset = mPendingXOffset; xOffsetStep = mPendingXOffsetStep; wallpaperDimAmount = mWallpaperDimAmount; } if (DEBUG) { Log.d(TAG, "processLocalColors " + xOffset + " of step " + xOffsetStep); Loading Loading @@ -1744,7 +1726,7 @@ public abstract class WallpaperService extends Service { xPage = mWindowPages.length - 1; } current = mWindowPages[xPage]; updatePage(current, xPage, xPages, wallpaperDimAmount); updatePage(current, xPage, xPages, finalXOffsetStep); Trace.endSection(); } Loading @@ -1764,23 +1746,16 @@ public abstract class WallpaperService extends Service { } } /** * Must be called with the surface lock held. * Must not be called if the surface is not valid. * Will unlock the surface when done using it. */ void updatePage(EngineWindowPage currentPage, int pageIndx, int numPages, float wallpaperDimAmount) { assertBackgroundThread(); float xOffsetStep) { // in case the clock is zero, we start with negative time long current = SystemClock.elapsedRealtime() - DEFAULT_UPDATE_SCREENSHOT_DURATION; long lapsed = current - currentPage.getLastUpdateTime(); // Always update the page when the last update time is <= 0 // This is important especially when the device first boots if (lapsed < DEFAULT_UPDATE_SCREENSHOT_DURATION) return; if (lapsed < DEFAULT_UPDATE_SCREENSHOT_DURATION) { return; } Surface surface = mSurfaceHolder.getSurface(); if (!surface.isValid()) return; boolean widthIsLarger = mSurfaceSize.x > mSurfaceSize.y; Loading @@ -1796,12 +1771,9 @@ public abstract class WallpaperService extends Service { Bitmap screenShot = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888); final Bitmap finalScreenShot = screenShot; final String pixelCopySectionName = "WallpaperService#pixelCopy"; final int pixelCopyCount = mPixelCopyCount++; Trace.beginAsyncSection(pixelCopySectionName, pixelCopyCount); try { Trace.beginSection("WallpaperService#pixelCopy"); PixelCopy.request(surface, screenShot, (res) -> { Trace.endAsyncSection(pixelCopySectionName, pixelCopyCount); Trace.endSection(); if (DEBUG) Log.d(TAG, "result of pixel copy is " + res); if (res != PixelCopy.SUCCESS) { Bitmap lastBitmap = currentPage.getBitmap(); Loading @@ -1810,28 +1782,22 @@ public abstract class WallpaperService extends Service { Bitmap lastScreenshot = mLastScreenshot; if (lastScreenshot != null && !lastScreenshot.isRecycled() && !Objects.equals(lastBitmap, lastScreenshot)) { updatePageColors(currentPage, pageIndx, numPages, wallpaperDimAmount); updatePageColors(currentPage, pageIndx, numPages, xOffsetStep); } } else { mLastScreenshot = finalScreenShot; // going to hold this lock for a while currentPage.setBitmap(finalScreenShot); currentPage.setLastUpdateTime(current); updatePageColors(currentPage, 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.i(TAG, "Cancelling processLocalColors: exception caught during PixelCopy"); updatePageColors(currentPage, pageIndx, numPages, xOffsetStep); } }, mHandler); } // locked by the passed page private void updatePageColors( EngineWindowPage page, int pageIndx, int numPages, float wallpaperDimAmount) { private void updatePageColors(EngineWindowPage page, int pageIndx, int numPages, float xOffsetStep) { if (page.getBitmap() == null) return; assertBackgroundThread(); Trace.beginSection("WallpaperService#updatePageColors"); if (DEBUG) { Log.d(TAG, "updatePageColorsLocked for page " + pageIndx + " with areas " Loading @@ -1853,7 +1819,7 @@ public abstract class WallpaperService extends Service { Log.e(TAG, "Error creating page local color bitmap", e); continue; } WallpaperColors color = WallpaperColors.fromBitmap(target, wallpaperDimAmount); WallpaperColors color = WallpaperColors.fromBitmap(target, mWallpaperDimAmount); target.recycle(); WallpaperColors currentColor = page.getColors(area); Loading @@ -1870,26 +1836,17 @@ public abstract class WallpaperService extends Service { + " local color callback for area" + area + " for page " + pageIndx + " of " + numPages); } mHandler.post(() -> { try { mConnection.onLocalWallpaperColorsChanged(area, color, mDisplayContext.getDisplayId()); } catch (RemoteException e) { Log.e(TAG, "Error calling Connection.onLocalWallpaperColorsChanged", e); } }); } } Trace.endSection(); } private void assertBackgroundThread() { if (!mBackgroundHandler.getLooper().isCurrentThread()) { throw new IllegalStateException( "ProcessLocalColors should be called from the background thread"); } } private RectF generateSubRect(RectF in, int pageInx, int numPages) { float minLeft = (float) (pageInx) / (float) (numPages); float maxRight = (float) (pageInx + 1) / (float) (numPages); Loading @@ -1914,6 +1871,7 @@ public abstract class WallpaperService extends Service { if (supportsLocalColorExtraction()) return; if (!mResetWindowPages) return; mResetWindowPages = false; mLastWindowPage = -1; for (int i = 0; i < mWindowPages.length; i++) { mWindowPages[i].setLastUpdateTime(0L); } Loading @@ -1939,10 +1897,12 @@ public abstract class WallpaperService extends Service { if (DEBUG) { Log.d(TAG, "addLocalColorsAreas adding local color areas " + regions); } mBackgroundHandler.post(() -> { mHandler.post(() -> { mLocalColorsToAdd.addAll(regions); processLocalColors(); processLocalColors(mPendingXOffset, mPendingYOffset); }); } /** Loading @@ -1952,7 +1912,7 @@ public abstract class WallpaperService extends Service { */ public void removeLocalColorsAreas(@NonNull List<RectF> regions) { if (supportsLocalColorExtraction()) return; mBackgroundHandler.post(() -> { mHandler.post(() -> { float step = mPendingXOffsetStep; mLocalColorsToAdd.removeAll(regions); mLocalColorAreas.removeAll(regions); Loading Loading @@ -2618,9 +2578,6 @@ public abstract class WallpaperService extends Service { @Override public void onCreate() { Trace.beginSection("WPMS.onCreate"); mBackgroundThread = new HandlerThread("DefaultWallpaperLocalColorExtractor"); mBackgroundThread.start(); mBackgroundHandler = new Handler(mBackgroundThread.getLooper()); super.onCreate(); Trace.endSection(); } Loading @@ -2633,7 +2590,6 @@ public abstract class WallpaperService extends Service { engineWrapper.destroy(); } mActiveEngines.clear(); mBackgroundThread.quitSafely(); Trace.endSection(); } Loading Loading
core/java/android/service/wallpaper/WallpaperService.java +61 −105 Original line number Diff line number Diff line Loading @@ -60,7 +60,6 @@ import android.hardware.display.DisplayManager.DisplayListener; import android.os.Build; import android.os.Bundle; import android.os.Handler; import android.os.HandlerThread; import android.os.IBinder; import android.os.Looper; import android.os.Message; Loading Loading @@ -181,9 +180,6 @@ public abstract class WallpaperService extends Service { private final ArrayMap<IBinder, IWallpaperEngineWrapper> mActiveEngines = new ArrayMap<>(); private Handler mBackgroundHandler; private HandlerThread mBackgroundThread; static final class WallpaperCommand { String action; int x; Loading @@ -202,6 +198,14 @@ public abstract class WallpaperService extends Service { */ public class Engine { 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. HandlerCaller mCaller; Loading Loading @@ -262,27 +266,11 @@ public abstract class WallpaperService extends Service { final Object mLock = new Object(); boolean mOffsetMessageEnqueued; @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023) float mPendingXOffset; float mPendingYOffset; float mPendingXOffsetStep; float mPendingYOffsetStep; /** * local color extraction related fields * to be used by the background thread only (except the atomic boolean) */ final ArraySet<RectF> mLocalColorAreas = new ArraySet<>(4); 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 EngineWindowPage[] mWindowPages = new EngineWindowPage[0]; Bitmap mLastScreenshot; private boolean mResetWindowPages; boolean mPendingSync; MotionEvent mPendingMove; boolean mIsInAmbientMode; Loading @@ -291,8 +279,12 @@ public abstract class WallpaperService extends Service { private long mLastColorInvalidation; 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 Handler mHandler; private Display mDisplay; private Context mDisplayContext; private int mDisplayState; Loading Loading @@ -862,7 +854,7 @@ public abstract class WallpaperService extends Service { + "was not established."); } mResetWindowPages = true; processLocalColors(); processLocalColors(mPendingXOffset, mPendingXOffsetStep); } catch (RemoteException e) { Log.w(TAG, "Can't notify system because wallpaper connection was lost.", e); } Loading Loading @@ -1400,7 +1392,7 @@ public abstract class WallpaperService extends Service { resetWindowPages(); mSession.finishDrawing(mWindow, null /* postDrawTransaction */, Integer.MAX_VALUE); processLocalColors(); processLocalColors(mPendingXOffset, mPendingXOffsetStep); } reposition(); reportEngineShown(shouldWaitForEngineShown()); Loading Loading @@ -1544,7 +1536,7 @@ public abstract class WallpaperService extends Service { if (!mDestroyed) { mVisible = visible; reportVisibility(false); if (mReportedVisible) processLocalColors(); if (mReportedVisible) processLocalColors(mPendingXOffset, mPendingXOffsetStep); } else { AnimationHandler.requestAnimatorsEnabled(visible, this); } Loading Loading @@ -1647,41 +1639,31 @@ public abstract class WallpaperService extends Service { } // setup local color extraction data processLocalColors(); processLocalColors(xOffset, xOffsetStep); } /** * Thread-safe util to call {@link #processLocalColorsInternal} with a minimum interval of * {@link #PROCESS_LOCAL_COLORS_INTERVAL_MS} between two calls. */ private void processLocalColors() { private void processLocalColors(float xOffset, float xOffsetStep) { if (mProcessLocalColorsPending.compareAndSet(false, true)) { final long now = mClockFunction.get(); final long timeSinceLastColorProcess = now - mLastProcessLocalColorsTimestamp; final long timeToWait = Math.max(0, PROCESS_LOCAL_COLORS_INTERVAL_MS - timeSinceLastColorProcess); mBackgroundHandler.postDelayed(() -> { mHandler.postDelayed(() -> { mLastProcessLocalColorsTimestamp = now + timeToWait; mProcessLocalColorsPending.set(false); processLocalColorsInternal(); processLocalColorsInternal(xOffset, xOffsetStep); }, timeToWait); } } private void processLocalColorsInternal() { private void processLocalColorsInternal(float xOffset, float xOffsetStep) { // implemented by the wallpaper if (supportsLocalColorExtraction()) return; assertBackgroundThread(); float xOffset; float xOffsetStep; float wallpaperDimAmount; synchronized (mLock) { xOffset = mPendingXOffset; xOffsetStep = mPendingXOffsetStep; wallpaperDimAmount = mWallpaperDimAmount; } if (DEBUG) { Log.d(TAG, "processLocalColors " + xOffset + " of step " + xOffsetStep); Loading Loading @@ -1744,7 +1726,7 @@ public abstract class WallpaperService extends Service { xPage = mWindowPages.length - 1; } current = mWindowPages[xPage]; updatePage(current, xPage, xPages, wallpaperDimAmount); updatePage(current, xPage, xPages, finalXOffsetStep); Trace.endSection(); } Loading @@ -1764,23 +1746,16 @@ public abstract class WallpaperService extends Service { } } /** * Must be called with the surface lock held. * Must not be called if the surface is not valid. * Will unlock the surface when done using it. */ void updatePage(EngineWindowPage currentPage, int pageIndx, int numPages, float wallpaperDimAmount) { assertBackgroundThread(); float xOffsetStep) { // in case the clock is zero, we start with negative time long current = SystemClock.elapsedRealtime() - DEFAULT_UPDATE_SCREENSHOT_DURATION; long lapsed = current - currentPage.getLastUpdateTime(); // Always update the page when the last update time is <= 0 // This is important especially when the device first boots if (lapsed < DEFAULT_UPDATE_SCREENSHOT_DURATION) return; if (lapsed < DEFAULT_UPDATE_SCREENSHOT_DURATION) { return; } Surface surface = mSurfaceHolder.getSurface(); if (!surface.isValid()) return; boolean widthIsLarger = mSurfaceSize.x > mSurfaceSize.y; Loading @@ -1796,12 +1771,9 @@ public abstract class WallpaperService extends Service { Bitmap screenShot = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888); final Bitmap finalScreenShot = screenShot; final String pixelCopySectionName = "WallpaperService#pixelCopy"; final int pixelCopyCount = mPixelCopyCount++; Trace.beginAsyncSection(pixelCopySectionName, pixelCopyCount); try { Trace.beginSection("WallpaperService#pixelCopy"); PixelCopy.request(surface, screenShot, (res) -> { Trace.endAsyncSection(pixelCopySectionName, pixelCopyCount); Trace.endSection(); if (DEBUG) Log.d(TAG, "result of pixel copy is " + res); if (res != PixelCopy.SUCCESS) { Bitmap lastBitmap = currentPage.getBitmap(); Loading @@ -1810,28 +1782,22 @@ public abstract class WallpaperService extends Service { Bitmap lastScreenshot = mLastScreenshot; if (lastScreenshot != null && !lastScreenshot.isRecycled() && !Objects.equals(lastBitmap, lastScreenshot)) { updatePageColors(currentPage, pageIndx, numPages, wallpaperDimAmount); updatePageColors(currentPage, pageIndx, numPages, xOffsetStep); } } else { mLastScreenshot = finalScreenShot; // going to hold this lock for a while currentPage.setBitmap(finalScreenShot); currentPage.setLastUpdateTime(current); updatePageColors(currentPage, 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.i(TAG, "Cancelling processLocalColors: exception caught during PixelCopy"); updatePageColors(currentPage, pageIndx, numPages, xOffsetStep); } }, mHandler); } // locked by the passed page private void updatePageColors( EngineWindowPage page, int pageIndx, int numPages, float wallpaperDimAmount) { private void updatePageColors(EngineWindowPage page, int pageIndx, int numPages, float xOffsetStep) { if (page.getBitmap() == null) return; assertBackgroundThread(); Trace.beginSection("WallpaperService#updatePageColors"); if (DEBUG) { Log.d(TAG, "updatePageColorsLocked for page " + pageIndx + " with areas " Loading @@ -1853,7 +1819,7 @@ public abstract class WallpaperService extends Service { Log.e(TAG, "Error creating page local color bitmap", e); continue; } WallpaperColors color = WallpaperColors.fromBitmap(target, wallpaperDimAmount); WallpaperColors color = WallpaperColors.fromBitmap(target, mWallpaperDimAmount); target.recycle(); WallpaperColors currentColor = page.getColors(area); Loading @@ -1870,26 +1836,17 @@ public abstract class WallpaperService extends Service { + " local color callback for area" + area + " for page " + pageIndx + " of " + numPages); } mHandler.post(() -> { try { mConnection.onLocalWallpaperColorsChanged(area, color, mDisplayContext.getDisplayId()); } catch (RemoteException e) { Log.e(TAG, "Error calling Connection.onLocalWallpaperColorsChanged", e); } }); } } Trace.endSection(); } private void assertBackgroundThread() { if (!mBackgroundHandler.getLooper().isCurrentThread()) { throw new IllegalStateException( "ProcessLocalColors should be called from the background thread"); } } private RectF generateSubRect(RectF in, int pageInx, int numPages) { float minLeft = (float) (pageInx) / (float) (numPages); float maxRight = (float) (pageInx + 1) / (float) (numPages); Loading @@ -1914,6 +1871,7 @@ public abstract class WallpaperService extends Service { if (supportsLocalColorExtraction()) return; if (!mResetWindowPages) return; mResetWindowPages = false; mLastWindowPage = -1; for (int i = 0; i < mWindowPages.length; i++) { mWindowPages[i].setLastUpdateTime(0L); } Loading @@ -1939,10 +1897,12 @@ public abstract class WallpaperService extends Service { if (DEBUG) { Log.d(TAG, "addLocalColorsAreas adding local color areas " + regions); } mBackgroundHandler.post(() -> { mHandler.post(() -> { mLocalColorsToAdd.addAll(regions); processLocalColors(); processLocalColors(mPendingXOffset, mPendingYOffset); }); } /** Loading @@ -1952,7 +1912,7 @@ public abstract class WallpaperService extends Service { */ public void removeLocalColorsAreas(@NonNull List<RectF> regions) { if (supportsLocalColorExtraction()) return; mBackgroundHandler.post(() -> { mHandler.post(() -> { float step = mPendingXOffsetStep; mLocalColorsToAdd.removeAll(regions); mLocalColorAreas.removeAll(regions); Loading Loading @@ -2618,9 +2578,6 @@ public abstract class WallpaperService extends Service { @Override public void onCreate() { Trace.beginSection("WPMS.onCreate"); mBackgroundThread = new HandlerThread("DefaultWallpaperLocalColorExtractor"); mBackgroundThread.start(); mBackgroundHandler = new Handler(mBackgroundThread.getLooper()); super.onCreate(); Trace.endSection(); } Loading @@ -2633,7 +2590,6 @@ public abstract class WallpaperService extends Service { engineWrapper.destroy(); } mActiveEngines.clear(); mBackgroundThread.quitSafely(); Trace.endSection(); } Loading