Merge "Rate limit notifyColorsChanged()" into oc-mr1-dev
This commit is contained in:
committed by
Android (Google) Code Review
commit
9d836b6312
@@ -33,10 +33,12 @@ import android.graphics.drawable.Drawable;
|
||||
import android.hardware.display.DisplayManager;
|
||||
import android.hardware.display.DisplayManager.DisplayListener;
|
||||
import android.os.Bundle;
|
||||
import android.os.Handler;
|
||||
import android.os.IBinder;
|
||||
import android.os.Looper;
|
||||
import android.os.Message;
|
||||
import android.os.RemoteException;
|
||||
import android.os.SystemClock;
|
||||
import android.util.Log;
|
||||
import android.util.MergedConfiguration;
|
||||
import android.view.Display;
|
||||
@@ -54,6 +56,7 @@ import android.view.WindowInsets;
|
||||
import android.view.WindowManager;
|
||||
import android.view.WindowManagerGlobal;
|
||||
|
||||
import com.android.internal.annotations.VisibleForTesting;
|
||||
import com.android.internal.os.HandlerCaller;
|
||||
import com.android.internal.view.BaseIWindow;
|
||||
import com.android.internal.view.BaseSurfaceHolder;
|
||||
@@ -61,6 +64,7 @@ import com.android.internal.view.BaseSurfaceHolder;
|
||||
import java.io.FileDescriptor;
|
||||
import java.io.PrintWriter;
|
||||
import java.util.ArrayList;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
/**
|
||||
* A wallpaper service is responsible for showing a live wallpaper behind
|
||||
@@ -106,7 +110,9 @@ public abstract class WallpaperService extends Service {
|
||||
private static final int MSG_WINDOW_MOVED = 10035;
|
||||
private static final int MSG_TOUCH_EVENT = 10040;
|
||||
private static final int MSG_REQUEST_WALLPAPER_COLORS = 10050;
|
||||
|
||||
|
||||
private static final int NOTIFY_COLORS_RATE_LIMIT_MS = 1000;
|
||||
|
||||
private final ArrayList<Engine> mActiveEngines
|
||||
= new ArrayList<Engine>();
|
||||
|
||||
@@ -186,6 +192,11 @@ public abstract class WallpaperService extends Service {
|
||||
boolean mPendingSync;
|
||||
MotionEvent mPendingMove;
|
||||
|
||||
// Needed for throttling onComputeColors.
|
||||
private long mLastColorInvalidation;
|
||||
private final Runnable mNotifyColorsChanged = this::notifyColorsChanged;
|
||||
private Supplier<Long> mClockFunction = SystemClock::elapsedRealtime;
|
||||
|
||||
DisplayManager mDisplayManager;
|
||||
Display mDisplay;
|
||||
private int mDisplayState;
|
||||
@@ -551,18 +562,38 @@ public abstract class WallpaperService extends Service {
|
||||
* This will trigger a {@link #onComputeColors()} call.
|
||||
*/
|
||||
public void notifyColorsChanged() {
|
||||
final long now = mClockFunction.get();
|
||||
final Handler mainHandler = Handler.getMain();
|
||||
if (now - mLastColorInvalidation < NOTIFY_COLORS_RATE_LIMIT_MS) {
|
||||
Log.w(TAG, "This call has been deferred. You should only call "
|
||||
+ "notifyColorsChanged() once every "
|
||||
+ (NOTIFY_COLORS_RATE_LIMIT_MS / 1000f) + " seconds.");
|
||||
if (!mainHandler.hasCallbacks(mNotifyColorsChanged)) {
|
||||
mainHandler.postDelayed(mNotifyColorsChanged, NOTIFY_COLORS_RATE_LIMIT_MS);
|
||||
}
|
||||
return;
|
||||
}
|
||||
mLastColorInvalidation = now;
|
||||
mainHandler.removeCallbacks(mNotifyColorsChanged);
|
||||
|
||||
try {
|
||||
mConnection.onWallpaperColorsChanged(onComputeColors());
|
||||
final WallpaperColors newColors = onComputeColors();
|
||||
if (mConnection != null) {
|
||||
mConnection.onWallpaperColorsChanged(newColors);
|
||||
} else {
|
||||
Log.w(TAG, "Can't notify system because wallpaper connection "
|
||||
+ "was not established.");
|
||||
}
|
||||
} catch (RemoteException e) {
|
||||
Log.w(TAG, "Can't invalidate wallpaper colors because " +
|
||||
"wallpaper connection was lost", e);
|
||||
Log.w(TAG, "Can't notify system because wallpaper connection was lost.", e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Called by the system when it needs to know what colors the wallpaper is using.
|
||||
* You might return null if no color information is available at the moment. In that case
|
||||
* you might want to call {@link #notifyColorsChanged()} in a near future.
|
||||
* You might return null if no color information is available at the moment.
|
||||
* In that case you might want to call {@link #notifyColorsChanged()} when
|
||||
* color information becomes available.
|
||||
* <p>
|
||||
* The simplest way of creating a {@link android.app.WallpaperColors} object is by using
|
||||
* {@link android.app.WallpaperColors#fromBitmap(Bitmap)} or
|
||||
@@ -631,6 +662,14 @@ public abstract class WallpaperService extends Service {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @hide
|
||||
*/
|
||||
@VisibleForTesting
|
||||
public void setClockFunction(Supplier<Long> clockFunction) {
|
||||
mClockFunction = clockFunction;
|
||||
}
|
||||
|
||||
void updateSurface(boolean forceRelayout, boolean forceReport, boolean redrawNeeded) {
|
||||
if (mDestroyed) {
|
||||
Log.w(TAG, "Ignoring updateSurface: destroyed");
|
||||
@@ -893,7 +932,7 @@ public abstract class WallpaperService extends Service {
|
||||
" w=" + mLayout.width + " h=" + mLayout.height);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void attach(IWallpaperEngineWrapper wrapper) {
|
||||
if (DEBUG) Log.v(TAG, "attach: " + this + " wrapper=" + wrapper);
|
||||
if (mDestroyed) {
|
||||
|
||||
@@ -0,0 +1,68 @@
|
||||
/*
|
||||
* 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.server.wallpaper;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
||||
import android.app.WallpaperColors;
|
||||
import android.os.SystemClock;
|
||||
import android.service.wallpaper.WallpaperService;
|
||||
import android.support.test.filters.SmallTest;
|
||||
import android.support.test.runner.AndroidJUnit4;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
|
||||
import java.util.concurrent.CountDownLatch;
|
||||
|
||||
@SmallTest
|
||||
@RunWith(AndroidJUnit4.class)
|
||||
public class WallpaperServiceTests {
|
||||
|
||||
@Test
|
||||
public void testNotifyColorsChanged_rateLimit() throws Exception {
|
||||
CountDownLatch eventCountdown = new CountDownLatch(2);
|
||||
WallpaperService service = new WallpaperService() {
|
||||
@Override
|
||||
public Engine onCreateEngine() {
|
||||
return new WallpaperService.Engine() {
|
||||
@Override
|
||||
public WallpaperColors onComputeColors() {
|
||||
eventCountdown.countDown();
|
||||
return null;
|
||||
}
|
||||
};
|
||||
}
|
||||
};
|
||||
WallpaperService.Engine engine = service.onCreateEngine();
|
||||
|
||||
// Called because it's the first time.
|
||||
engine.notifyColorsChanged();
|
||||
assertEquals("OnComputeColors should have been called.",
|
||||
1, eventCountdown.getCount());
|
||||
|
||||
// Ignored since the call should be throttled.
|
||||
engine.notifyColorsChanged();
|
||||
assertEquals("OnComputeColors should have been throttled.",
|
||||
1, eventCountdown.getCount());
|
||||
// Called after being deferred.
|
||||
engine.setClockFunction(() -> SystemClock.elapsedRealtime() + 1500);
|
||||
engine.notifyColorsChanged();
|
||||
assertEquals("OnComputeColors should have been deferred.",
|
||||
0, eventCountdown.getCount());
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user