DO NOT MERGE: Fix temporary black after setting a new image wallpaper
Sometimes see temporary black wallpaper after setting a new image wallpaper because of: - decode bitmap twice, results in long latency until drawing. - the set wallpaper apis didn't sync with wallpaper rendering well. Solutions: - Only decode bitmap when necessary. - Make set wallpaper apis wait for image wallpaper rendering finished. Bug: 194080642 Test: see b/194080642#comment3 Test: atest WallpaperManagerServiceTests --iterations 50 Test: atest SystemUITests Change-Id: I369eff5195571161cf286b3ec97175481b02eed7
This commit is contained in:
@@ -559,6 +559,53 @@ public class WallpaperManager {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Rect peekWallpaperDimensions(Context context, boolean returnDefault, int userId) {
|
||||||
|
if (mService != null) {
|
||||||
|
try {
|
||||||
|
if (!mService.isWallpaperSupported(context.getOpPackageName())) {
|
||||||
|
return new Rect();
|
||||||
|
}
|
||||||
|
} catch (RemoteException e) {
|
||||||
|
throw e.rethrowFromSystemServer();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Rect dimensions = null;
|
||||||
|
synchronized (this) {
|
||||||
|
try {
|
||||||
|
Bundle params = new Bundle();
|
||||||
|
// Let's peek user wallpaper first.
|
||||||
|
ParcelFileDescriptor pfd = mService.getWallpaperWithFeature(
|
||||||
|
context.getOpPackageName(), context.getAttributionTag(), this,
|
||||||
|
FLAG_SYSTEM, params, userId);
|
||||||
|
if (pfd != null) {
|
||||||
|
BitmapFactory.Options options = new BitmapFactory.Options();
|
||||||
|
options.inJustDecodeBounds = true;
|
||||||
|
BitmapFactory.decodeFileDescriptor(pfd.getFileDescriptor(), null, options);
|
||||||
|
dimensions = new Rect(0, 0, options.outWidth, options.outHeight);
|
||||||
|
}
|
||||||
|
} catch (RemoteException ex) {
|
||||||
|
Log.w(TAG, "peek wallpaper dimensions failed", ex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// If user wallpaper is unavailable, may be the default one instead.
|
||||||
|
if ((dimensions == null || dimensions.width() == 0 || dimensions.height() == 0)
|
||||||
|
&& returnDefault) {
|
||||||
|
InputStream is = openDefaultWallpaper(context, FLAG_SYSTEM);
|
||||||
|
if (is != null) {
|
||||||
|
try {
|
||||||
|
BitmapFactory.Options options = new BitmapFactory.Options();
|
||||||
|
options.inJustDecodeBounds = true;
|
||||||
|
BitmapFactory.decodeStream(is, null, options);
|
||||||
|
dimensions = new Rect(0, 0, options.outWidth, options.outHeight);
|
||||||
|
} finally {
|
||||||
|
IoUtils.closeQuietly(is);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return dimensions;
|
||||||
|
}
|
||||||
|
|
||||||
void forgetLoadedWallpaper() {
|
void forgetLoadedWallpaper() {
|
||||||
synchronized (this) {
|
synchronized (this) {
|
||||||
mCachedWallpaper = null;
|
mCachedWallpaper = null;
|
||||||
@@ -1038,6 +1085,17 @@ public class WallpaperManager {
|
|||||||
return sGlobals.peekWallpaperBitmap(mContext, true, FLAG_SYSTEM, userId, hardware, cmProxy);
|
return sGlobals.peekWallpaperBitmap(mContext, true, FLAG_SYSTEM, userId, hardware, cmProxy);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Peek the dimensions of system wallpaper of the user without decoding it.
|
||||||
|
*
|
||||||
|
* @return the dimensions of system wallpaper
|
||||||
|
* @hide
|
||||||
|
*/
|
||||||
|
public Rect peekBitmapDimensions() {
|
||||||
|
return sGlobals.peekWallpaperDimensions(
|
||||||
|
mContext, true /* returnDefault */, mContext.getUserId());
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get an open, readable file descriptor to the given wallpaper image file.
|
* Get an open, readable file descriptor to the given wallpaper image file.
|
||||||
* The caller is responsible for closing the file descriptor when done ingesting the file.
|
* The caller is responsible for closing the file descriptor when done ingesting the file.
|
||||||
|
|||||||
@@ -96,6 +96,7 @@ import java.util.ArrayList;
|
|||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
|
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;
|
||||||
|
|
||||||
@@ -152,6 +153,7 @@ public abstract class WallpaperService extends Service {
|
|||||||
private static final int MSG_REQUEST_WALLPAPER_COLORS = 10050;
|
private static final int MSG_REQUEST_WALLPAPER_COLORS = 10050;
|
||||||
private static final int MSG_ZOOM = 10100;
|
private static final int MSG_ZOOM = 10100;
|
||||||
private static final int MSG_SCALE_PREVIEW = 10110;
|
private static final int MSG_SCALE_PREVIEW = 10110;
|
||||||
|
private static final int MSG_REPORT_SHOWN = 10150;
|
||||||
private static final List<Float> PROHIBITED_STEPS = Arrays.asList(0f, Float.POSITIVE_INFINITY,
|
private static final List<Float> PROHIBITED_STEPS = Arrays.asList(0f, Float.POSITIVE_INFINITY,
|
||||||
Float.NEGATIVE_INFINITY);
|
Float.NEGATIVE_INFINITY);
|
||||||
|
|
||||||
@@ -526,6 +528,35 @@ public abstract class WallpaperService extends Service {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This will be called in the end of {@link #updateSurface(boolean, boolean, boolean)}.
|
||||||
|
* If true is returned, the engine will not report shown until rendering finished is
|
||||||
|
* reported. Otherwise, the engine will report shown immediately right after redraw phase
|
||||||
|
* in {@link #updateSurface(boolean, boolean, boolean)}.
|
||||||
|
*
|
||||||
|
* @hide
|
||||||
|
*/
|
||||||
|
public boolean shouldWaitForEngineShown() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reports the rendering is finished, stops waiting, then invokes
|
||||||
|
* {@link IWallpaperEngineWrapper#reportShown()}.
|
||||||
|
*
|
||||||
|
* @hide
|
||||||
|
*/
|
||||||
|
public void reportEngineShown(boolean waitForEngineShown) {
|
||||||
|
if (mIWallpaperEngine.mShownReported) return;
|
||||||
|
Message message = mCaller.obtainMessage(MSG_REPORT_SHOWN);
|
||||||
|
if (!waitForEngineShown) {
|
||||||
|
mCaller.removeMessages(MSG_REPORT_SHOWN);
|
||||||
|
mCaller.sendMessage(message);
|
||||||
|
} else {
|
||||||
|
mCaller.sendMessageDelayed(message, TimeUnit.SECONDS.toMillis(1));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Control whether this wallpaper will receive raw touch events
|
* Control whether this wallpaper will receive raw touch events
|
||||||
* from the window manager as the user interacts with the window
|
* from the window manager as the user interacts with the window
|
||||||
@@ -930,7 +961,7 @@ public abstract class WallpaperService extends Service {
|
|||||||
|
|
||||||
void updateSurface(boolean forceRelayout, boolean forceReport, boolean redrawNeeded) {
|
void updateSurface(boolean forceRelayout, boolean forceReport, boolean redrawNeeded) {
|
||||||
if (mDestroyed) {
|
if (mDestroyed) {
|
||||||
Log.w(TAG, "Ignoring updateSurface: destroyed");
|
Log.w(TAG, "Ignoring updateSurface due to destroyed");
|
||||||
}
|
}
|
||||||
|
|
||||||
boolean fixedSize = false;
|
boolean fixedSize = false;
|
||||||
@@ -1197,7 +1228,6 @@ public abstract class WallpaperService extends Service {
|
|||||||
+ this);
|
+ this);
|
||||||
onVisibilityChanged(false);
|
onVisibilityChanged(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
} finally {
|
} finally {
|
||||||
mIsCreating = false;
|
mIsCreating = false;
|
||||||
mSurfaceCreated = true;
|
mSurfaceCreated = true;
|
||||||
@@ -1207,7 +1237,7 @@ public abstract class WallpaperService extends Service {
|
|||||||
processLocalColors(mPendingXOffset, mPendingXOffsetStep);
|
processLocalColors(mPendingXOffset, mPendingXOffsetStep);
|
||||||
}
|
}
|
||||||
reposition();
|
reposition();
|
||||||
mIWallpaperEngine.reportShown();
|
reportEngineShown(shouldWaitForEngineShown());
|
||||||
}
|
}
|
||||||
} catch (RemoteException ex) {
|
} catch (RemoteException ex) {
|
||||||
}
|
}
|
||||||
@@ -2201,6 +2231,9 @@ public abstract class WallpaperService extends Service {
|
|||||||
// Connection went away, nothing to do in here.
|
// Connection went away, nothing to do in here.
|
||||||
}
|
}
|
||||||
} break;
|
} break;
|
||||||
|
case MSG_REPORT_SHOWN: {
|
||||||
|
reportShown();
|
||||||
|
} break;
|
||||||
default :
|
default :
|
||||||
Log.w(TAG, "Unknown message type " + message.what);
|
Log.w(TAG, "Unknown message type " + message.what);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -120,15 +120,16 @@ public class ImageWallpaper extends WallpaperService {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onCreate(SurfaceHolder surfaceHolder) {
|
public void onCreate(SurfaceHolder surfaceHolder) {
|
||||||
|
Trace.beginSection("ImageWallpaper.Engine#onCreate");
|
||||||
mEglHelper = getEglHelperInstance();
|
mEglHelper = getEglHelperInstance();
|
||||||
// Deferred init renderer because we need to get wallpaper by display context.
|
// Deferred init renderer because we need to get wallpaper by display context.
|
||||||
mRenderer = getRendererInstance();
|
mRenderer = getRendererInstance();
|
||||||
setFixedSizeAllowed(true);
|
setFixedSizeAllowed(true);
|
||||||
updateSurfaceSize();
|
updateSurfaceSize();
|
||||||
|
|
||||||
mRenderer.setOnBitmapChanged(this::updateMiniBitmap);
|
mRenderer.setOnBitmapChanged(this::updateMiniBitmap);
|
||||||
getDisplayContext().getSystemService(DisplayManager.class)
|
getDisplayContext().getSystemService(DisplayManager.class)
|
||||||
.registerDisplayListener(this, mWorker.getThreadHandler());
|
.registerDisplayListener(this, mWorker.getThreadHandler());
|
||||||
|
Trace.endSection();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -197,16 +198,23 @@ public class ImageWallpaper extends WallpaperService {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean shouldWaitForEngineShown() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onDestroy() {
|
public void onDestroy() {
|
||||||
getDisplayContext().getSystemService(DisplayManager.class)
|
getDisplayContext().getSystemService(DisplayManager.class)
|
||||||
.unregisterDisplayListener(this);
|
.unregisterDisplayListener(this);
|
||||||
mMiniBitmap = null;
|
mMiniBitmap = null;
|
||||||
mWorker.getThreadHandler().post(() -> {
|
mWorker.getThreadHandler().post(() -> {
|
||||||
|
Trace.beginSection("ImageWallpaper.Engine#onDestroy");
|
||||||
mRenderer.finish();
|
mRenderer.finish();
|
||||||
mRenderer = null;
|
mRenderer = null;
|
||||||
mEglHelper.finish();
|
mEglHelper.finish();
|
||||||
mEglHelper = null;
|
mEglHelper = null;
|
||||||
|
Trace.endSection();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -340,8 +348,10 @@ public class ImageWallpaper extends WallpaperService {
|
|||||||
public void onSurfaceCreated(SurfaceHolder holder) {
|
public void onSurfaceCreated(SurfaceHolder holder) {
|
||||||
if (mWorker == null) return;
|
if (mWorker == null) return;
|
||||||
mWorker.getThreadHandler().post(() -> {
|
mWorker.getThreadHandler().post(() -> {
|
||||||
|
Trace.beginSection("ImageWallpaper#onSurfaceCreated");
|
||||||
mEglHelper.init(holder, needSupportWideColorGamut());
|
mEglHelper.init(holder, needSupportWideColorGamut());
|
||||||
mRenderer.onSurfaceCreated();
|
mRenderer.onSurfaceCreated();
|
||||||
|
Trace.endSection();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -358,9 +368,11 @@ public class ImageWallpaper extends WallpaperService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void drawFrame() {
|
private void drawFrame() {
|
||||||
|
Trace.beginSection("ImageWallpaper#drawFrame");
|
||||||
preRender();
|
preRender();
|
||||||
requestRender();
|
requestRender();
|
||||||
postRender();
|
postRender();
|
||||||
|
Trace.endSection();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void preRender() {
|
public void preRender() {
|
||||||
@@ -427,6 +439,7 @@ public class ImageWallpaper extends WallpaperService {
|
|||||||
// This method should only be invoked from worker thread.
|
// This method should only be invoked from worker thread.
|
||||||
Trace.beginSection("ImageWallpaper#postRender");
|
Trace.beginSection("ImageWallpaper#postRender");
|
||||||
scheduleFinishRendering();
|
scheduleFinishRendering();
|
||||||
|
reportEngineShown(false /* waitForEngineShown */);
|
||||||
Trace.endSection();
|
Trace.endSection();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -102,7 +102,6 @@ public class ImageWallpaperRenderer implements GLWallpaperRenderer {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Size reportSurfaceSize() {
|
public Size reportSurfaceSize() {
|
||||||
mTexture.use(null /* consumer */);
|
|
||||||
mSurfaceSize.set(mTexture.getTextureDimensions());
|
mSurfaceSize.set(mTexture.getTextureDimensions());
|
||||||
return new Size(mSurfaceSize.width(), mSurfaceSize.height());
|
return new Size(mSurfaceSize.width(), mSurfaceSize.height());
|
||||||
}
|
}
|
||||||
@@ -124,6 +123,7 @@ public class ImageWallpaperRenderer implements GLWallpaperRenderer {
|
|||||||
private final WallpaperManager mWallpaperManager;
|
private final WallpaperManager mWallpaperManager;
|
||||||
private Bitmap mBitmap;
|
private Bitmap mBitmap;
|
||||||
private boolean mWcgContent;
|
private boolean mWcgContent;
|
||||||
|
private boolean mTextureUsed;
|
||||||
|
|
||||||
private WallpaperTexture(WallpaperManager wallpaperManager) {
|
private WallpaperTexture(WallpaperManager wallpaperManager) {
|
||||||
mWallpaperManager = wallpaperManager;
|
mWallpaperManager = wallpaperManager;
|
||||||
@@ -141,6 +141,7 @@ public class ImageWallpaperRenderer implements GLWallpaperRenderer {
|
|||||||
mWallpaperManager.forgetLoadedWallpaper();
|
mWallpaperManager.forgetLoadedWallpaper();
|
||||||
if (mBitmap != null) {
|
if (mBitmap != null) {
|
||||||
mDimensions.set(0, 0, mBitmap.getWidth(), mBitmap.getHeight());
|
mDimensions.set(0, 0, mBitmap.getWidth(), mBitmap.getHeight());
|
||||||
|
mTextureUsed = true;
|
||||||
} else {
|
} else {
|
||||||
Log.w(TAG, "Can't get bitmap");
|
Log.w(TAG, "Can't get bitmap");
|
||||||
}
|
}
|
||||||
@@ -171,6 +172,9 @@ public class ImageWallpaperRenderer implements GLWallpaperRenderer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private Rect getTextureDimensions() {
|
private Rect getTextureDimensions() {
|
||||||
|
if (!mTextureUsed) {
|
||||||
|
mDimensions.set(mWallpaperManager.peekBitmapDimensions());
|
||||||
|
}
|
||||||
return mDimensions;
|
return mDimensions;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -208,7 +208,7 @@ public class WallpaperManagerService extends IWallpaperManager.Stub
|
|||||||
* wallpaper set and is created for the first time. The CLOSE_WRITE is triggered
|
* wallpaper set and is created for the first time. The CLOSE_WRITE is triggered
|
||||||
* every time the wallpaper is changed.
|
* every time the wallpaper is changed.
|
||||||
*/
|
*/
|
||||||
private class WallpaperObserver extends FileObserver {
|
class WallpaperObserver extends FileObserver {
|
||||||
|
|
||||||
final int mUserId;
|
final int mUserId;
|
||||||
final WallpaperData mWallpaper;
|
final WallpaperData mWallpaper;
|
||||||
@@ -226,7 +226,7 @@ public class WallpaperManagerService extends IWallpaperManager.Stub
|
|||||||
mWallpaperLockFile = new File(mWallpaperDir, WALLPAPER_LOCK_ORIG);
|
mWallpaperLockFile = new File(mWallpaperDir, WALLPAPER_LOCK_ORIG);
|
||||||
}
|
}
|
||||||
|
|
||||||
private WallpaperData dataForEvent(boolean sysChanged, boolean lockChanged) {
|
WallpaperData dataForEvent(boolean sysChanged, boolean lockChanged) {
|
||||||
WallpaperData wallpaper = null;
|
WallpaperData wallpaper = null;
|
||||||
synchronized (mLock) {
|
synchronized (mLock) {
|
||||||
if (lockChanged) {
|
if (lockChanged) {
|
||||||
@@ -309,9 +309,18 @@ public class WallpaperManagerService extends IWallpaperManager.Stub
|
|||||||
}
|
}
|
||||||
wallpaper.imageWallpaperPending = false;
|
wallpaper.imageWallpaperPending = false;
|
||||||
if (sysWallpaperChanged) {
|
if (sysWallpaperChanged) {
|
||||||
|
IRemoteCallback.Stub callback = new IRemoteCallback.Stub() {
|
||||||
|
@Override
|
||||||
|
public void sendResult(Bundle data) throws RemoteException {
|
||||||
|
if (DEBUG) {
|
||||||
|
Slog.d(TAG, "publish system wallpaper changed!");
|
||||||
|
}
|
||||||
|
notifyWallpaperChanged(wallpaper);
|
||||||
|
}
|
||||||
|
};
|
||||||
// If this was the system wallpaper, rebind...
|
// If this was the system wallpaper, rebind...
|
||||||
bindWallpaperComponentLocked(mImageWallpaper, true,
|
bindWallpaperComponentLocked(mImageWallpaper, true,
|
||||||
false, wallpaper, null);
|
false, wallpaper, callback);
|
||||||
notifyColorsWhich |= FLAG_SYSTEM;
|
notifyColorsWhich |= FLAG_SYSTEM;
|
||||||
}
|
}
|
||||||
if (lockWallpaperChanged
|
if (lockWallpaperChanged
|
||||||
@@ -331,15 +340,9 @@ public class WallpaperManagerService extends IWallpaperManager.Stub
|
|||||||
}
|
}
|
||||||
|
|
||||||
saveSettingsLocked(wallpaper.userId);
|
saveSettingsLocked(wallpaper.userId);
|
||||||
|
// Notify the client immediately if only lockscreen wallpaper changed.
|
||||||
// Publish completion *after* we've persisted the changes
|
if (lockWallpaperChanged && !sysWallpaperChanged) {
|
||||||
if (wallpaper.setComplete != null) {
|
notifyWallpaperChanged(wallpaper);
|
||||||
try {
|
|
||||||
wallpaper.setComplete.onWallpaperChanged();
|
|
||||||
} catch (RemoteException e) {
|
|
||||||
// if this fails we don't really care; the setting app may just
|
|
||||||
// have crashed and that sort of thing is a fact of life.
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -353,6 +356,18 @@ public class WallpaperManagerService extends IWallpaperManager.Stub
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void notifyWallpaperChanged(WallpaperData wallpaper) {
|
||||||
|
// Publish completion *after* we've persisted the changes
|
||||||
|
if (wallpaper.setComplete != null) {
|
||||||
|
try {
|
||||||
|
wallpaper.setComplete.onWallpaperChanged();
|
||||||
|
} catch (RemoteException e) {
|
||||||
|
// if this fails we don't really care; the setting app may just
|
||||||
|
// have crashed and that sort of thing is a fact of life.
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private void notifyLockWallpaperChanged() {
|
private void notifyLockWallpaperChanged() {
|
||||||
final IWallpaperManagerCallback cb = mKeyguardListener;
|
final IWallpaperManagerCallback cb = mKeyguardListener;
|
||||||
if (cb != null) {
|
if (cb != null) {
|
||||||
@@ -364,7 +379,7 @@ public class WallpaperManagerService extends IWallpaperManager.Stub
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void notifyWallpaperColorsChanged(@NonNull WallpaperData wallpaper, int which) {
|
void notifyWallpaperColorsChanged(@NonNull WallpaperData wallpaper, int which) {
|
||||||
if (wallpaper.connection != null) {
|
if (wallpaper.connection != null) {
|
||||||
wallpaper.connection.forEachDisplayConnector(connector -> {
|
wallpaper.connection.forEachDisplayConnector(connector -> {
|
||||||
notifyWallpaperColorsChangedOnDisplay(wallpaper, which, connector.mDisplayId);
|
notifyWallpaperColorsChangedOnDisplay(wallpaper, which, connector.mDisplayId);
|
||||||
@@ -568,7 +583,7 @@ public class WallpaperManagerService extends IWallpaperManager.Stub
|
|||||||
* Once a new wallpaper has been written via setWallpaper(...), it needs to be cropped
|
* Once a new wallpaper has been written via setWallpaper(...), it needs to be cropped
|
||||||
* for display.
|
* for display.
|
||||||
*/
|
*/
|
||||||
private void generateCrop(WallpaperData wallpaper) {
|
void generateCrop(WallpaperData wallpaper) {
|
||||||
boolean success = false;
|
boolean success = false;
|
||||||
|
|
||||||
// Only generate crop for default display.
|
// Only generate crop for default display.
|
||||||
@@ -2834,7 +2849,7 @@ public class WallpaperManagerService extends IWallpaperManager.Stub
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean bindWallpaperComponentLocked(ComponentName componentName, boolean force,
|
boolean bindWallpaperComponentLocked(ComponentName componentName, boolean force,
|
||||||
boolean fromUser, WallpaperData wallpaper, IRemoteCallback reply) {
|
boolean fromUser, WallpaperData wallpaper, IRemoteCallback reply) {
|
||||||
if (DEBUG_LIVE) {
|
if (DEBUG_LIVE) {
|
||||||
Slog.v(TAG, "bindWallpaperComponentLocked: componentName=" + componentName);
|
Slog.v(TAG, "bindWallpaperComponentLocked: componentName=" + componentName);
|
||||||
@@ -3121,7 +3136,7 @@ public class WallpaperManagerService extends IWallpaperManager.Stub
|
|||||||
return new JournaledFile(new File(base), new File(base + ".tmp"));
|
return new JournaledFile(new File(base), new File(base + ".tmp"));
|
||||||
}
|
}
|
||||||
|
|
||||||
private void saveSettingsLocked(int userId) {
|
void saveSettingsLocked(int userId) {
|
||||||
JournaledFile journal = makeJournaledFile(userId);
|
JournaledFile journal = makeJournaledFile(userId);
|
||||||
FileOutputStream fstream = null;
|
FileOutputStream fstream = null;
|
||||||
try {
|
try {
|
||||||
@@ -3270,7 +3285,7 @@ public class WallpaperManagerService extends IWallpaperManager.Stub
|
|||||||
* Important: this method loads settings to initialize the given user's wallpaper data if
|
* Important: this method loads settings to initialize the given user's wallpaper data if
|
||||||
* there is no current in-memory state.
|
* there is no current in-memory state.
|
||||||
*/
|
*/
|
||||||
private WallpaperData getWallpaperSafeLocked(int userId, int which) {
|
WallpaperData getWallpaperSafeLocked(int userId, int which) {
|
||||||
// We're setting either just system (work with the system wallpaper),
|
// We're setting either just system (work with the system wallpaper),
|
||||||
// both (also work with the system wallpaper), or just the lock
|
// both (also work with the system wallpaper), or just the lock
|
||||||
// wallpaper (update against the existing lock wallpaper if any).
|
// wallpaper (update against the existing lock wallpaper if any).
|
||||||
|
|||||||
@@ -18,13 +18,18 @@ package com.android.server.wallpaper;
|
|||||||
|
|
||||||
import static android.app.WallpaperManager.COMMAND_REAPPLY;
|
import static android.app.WallpaperManager.COMMAND_REAPPLY;
|
||||||
import static android.app.WallpaperManager.FLAG_SYSTEM;
|
import static android.app.WallpaperManager.FLAG_SYSTEM;
|
||||||
|
import static android.os.FileObserver.CLOSE_WRITE;
|
||||||
|
import static android.os.UserHandle.USER_SYSTEM;
|
||||||
import static android.view.Display.DEFAULT_DISPLAY;
|
import static android.view.Display.DEFAULT_DISPLAY;
|
||||||
|
|
||||||
|
import static com.android.dx.mockito.inline.extended.ExtendedMockito.doAnswer;
|
||||||
import static com.android.dx.mockito.inline.extended.ExtendedMockito.doNothing;
|
import static com.android.dx.mockito.inline.extended.ExtendedMockito.doNothing;
|
||||||
import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn;
|
import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn;
|
||||||
import static com.android.dx.mockito.inline.extended.ExtendedMockito.mock;
|
import static com.android.dx.mockito.inline.extended.ExtendedMockito.mock;
|
||||||
import static com.android.dx.mockito.inline.extended.ExtendedMockito.mockitoSession;
|
import static com.android.dx.mockito.inline.extended.ExtendedMockito.mockitoSession;
|
||||||
import static com.android.dx.mockito.inline.extended.ExtendedMockito.spyOn;
|
import static com.android.dx.mockito.inline.extended.ExtendedMockito.spyOn;
|
||||||
|
import static com.android.server.wallpaper.WallpaperManagerService.WALLPAPER;
|
||||||
|
import static com.android.server.wallpaper.WallpaperManagerService.WALLPAPER_CROP;
|
||||||
|
|
||||||
import static org.hamcrest.core.IsNot.not;
|
import static org.hamcrest.core.IsNot.not;
|
||||||
import static org.junit.Assert.assertEquals;
|
import static org.junit.Assert.assertEquals;
|
||||||
@@ -34,6 +39,7 @@ import static org.junit.Assert.assertTrue;
|
|||||||
import static org.junit.Assert.fail;
|
import static org.junit.Assert.fail;
|
||||||
import static org.junit.Assume.assumeThat;
|
import static org.junit.Assume.assumeThat;
|
||||||
import static org.mockito.ArgumentMatchers.any;
|
import static org.mockito.ArgumentMatchers.any;
|
||||||
|
import static org.mockito.ArgumentMatchers.anyBoolean;
|
||||||
import static org.mockito.ArgumentMatchers.anyInt;
|
import static org.mockito.ArgumentMatchers.anyInt;
|
||||||
import static org.mockito.ArgumentMatchers.eq;
|
import static org.mockito.ArgumentMatchers.eq;
|
||||||
import static org.mockito.Mockito.reset;
|
import static org.mockito.Mockito.reset;
|
||||||
@@ -41,6 +47,7 @@ import static org.mockito.Mockito.verify;
|
|||||||
|
|
||||||
import android.app.AppGlobals;
|
import android.app.AppGlobals;
|
||||||
import android.app.AppOpsManager;
|
import android.app.AppOpsManager;
|
||||||
|
import android.app.WallpaperColors;
|
||||||
import android.app.WallpaperManager;
|
import android.app.WallpaperManager;
|
||||||
import android.content.ComponentName;
|
import android.content.ComponentName;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
@@ -49,8 +56,10 @@ import android.content.pm.IPackageManager;
|
|||||||
import android.content.pm.PackageManager;
|
import android.content.pm.PackageManager;
|
||||||
import android.content.pm.ParceledListSlice;
|
import android.content.pm.ParceledListSlice;
|
||||||
import android.content.pm.ServiceInfo;
|
import android.content.pm.ServiceInfo;
|
||||||
|
import android.graphics.Color;
|
||||||
import android.hardware.display.DisplayManager;
|
import android.hardware.display.DisplayManager;
|
||||||
import android.os.UserHandle;
|
import android.os.RemoteException;
|
||||||
|
import android.os.SystemClock;
|
||||||
import android.platform.test.annotations.Presubmit;
|
import android.platform.test.annotations.Presubmit;
|
||||||
import android.service.wallpaper.IWallpaperConnection;
|
import android.service.wallpaper.IWallpaperConnection;
|
||||||
import android.service.wallpaper.IWallpaperEngine;
|
import android.service.wallpaper.IWallpaperEngine;
|
||||||
@@ -143,7 +152,6 @@ public class WallpaperManagerServiceTests {
|
|||||||
sContext.getTestablePermissions().setPermission(
|
sContext.getTestablePermissions().setPermission(
|
||||||
android.Manifest.permission.SET_WALLPAPER,
|
android.Manifest.permission.SET_WALLPAPER,
|
||||||
PackageManager.PERMISSION_GRANTED);
|
PackageManager.PERMISSION_GRANTED);
|
||||||
doNothing().when(sContext).sendBroadcastAsUser(any(), any());
|
|
||||||
|
|
||||||
//Wallpaper components
|
//Wallpaper components
|
||||||
sWallpaperService = mock(IWallpaperConnection.Stub.class);
|
sWallpaperService = mock(IWallpaperConnection.Stub.class);
|
||||||
@@ -180,6 +188,7 @@ public class WallpaperManagerServiceTests {
|
|||||||
MockitoAnnotations.initMocks(this);
|
MockitoAnnotations.initMocks(this);
|
||||||
|
|
||||||
sContext.addMockSystemService(DisplayManager.class, mDisplayManager);
|
sContext.addMockSystemService(DisplayManager.class, mDisplayManager);
|
||||||
|
doNothing().when(sContext).sendBroadcastAsUser(any(), any());
|
||||||
|
|
||||||
final Display mockDisplay = mock(Display.class);
|
final Display mockDisplay = mock(Display.class);
|
||||||
doReturn(DISPLAY_SIZE_DIMENSION).when(mockDisplay).getMaximumSizeDimension();
|
doReturn(DISPLAY_SIZE_DIMENSION).when(mockDisplay).getMaximumSizeDimension();
|
||||||
@@ -242,13 +251,13 @@ public class WallpaperManagerServiceTests {
|
|||||||
*/
|
*/
|
||||||
@Test
|
@Test
|
||||||
public void testDataCorrectAfterBoot() {
|
public void testDataCorrectAfterBoot() {
|
||||||
mService.switchUser(UserHandle.USER_SYSTEM, null);
|
mService.switchUser(USER_SYSTEM, null);
|
||||||
|
|
||||||
final WallpaperData fallbackData = mService.mFallbackWallpaper;
|
final WallpaperData fallbackData = mService.mFallbackWallpaper;
|
||||||
assertEquals("Fallback wallpaper component should be ImageWallpaper.",
|
assertEquals("Fallback wallpaper component should be ImageWallpaper.",
|
||||||
sImageWallpaperComponentName, fallbackData.wallpaperComponent);
|
sImageWallpaperComponentName, fallbackData.wallpaperComponent);
|
||||||
|
|
||||||
verifyLastWallpaperData(UserHandle.USER_SYSTEM, sDefaultWallpaperComponent);
|
verifyLastWallpaperData(USER_SYSTEM, sDefaultWallpaperComponent);
|
||||||
verifyDisplayData();
|
verifyDisplayData();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -261,7 +270,7 @@ public class WallpaperManagerServiceTests {
|
|||||||
assumeThat(sDefaultWallpaperComponent,
|
assumeThat(sDefaultWallpaperComponent,
|
||||||
not(CoreMatchers.equalTo(sImageWallpaperComponentName)));
|
not(CoreMatchers.equalTo(sImageWallpaperComponentName)));
|
||||||
|
|
||||||
final int testUserId = UserHandle.USER_SYSTEM;
|
final int testUserId = USER_SYSTEM;
|
||||||
mService.switchUser(testUserId, null);
|
mService.switchUser(testUserId, null);
|
||||||
verifyLastWallpaperData(testUserId, sDefaultWallpaperComponent);
|
verifyLastWallpaperData(testUserId, sDefaultWallpaperComponent);
|
||||||
verifyCurrentSystemData(testUserId);
|
verifyCurrentSystemData(testUserId);
|
||||||
@@ -281,7 +290,7 @@ public class WallpaperManagerServiceTests {
|
|||||||
*/
|
*/
|
||||||
@Test
|
@Test
|
||||||
public void testSetCurrentComponent() throws Exception {
|
public void testSetCurrentComponent() throws Exception {
|
||||||
final int testUserId = UserHandle.USER_SYSTEM;
|
final int testUserId = USER_SYSTEM;
|
||||||
mService.switchUser(testUserId, null);
|
mService.switchUser(testUserId, null);
|
||||||
verifyLastWallpaperData(testUserId, sDefaultWallpaperComponent);
|
verifyLastWallpaperData(testUserId, sDefaultWallpaperComponent);
|
||||||
verifyCurrentSystemData(testUserId);
|
verifyCurrentSystemData(testUserId);
|
||||||
@@ -387,6 +396,42 @@ public class WallpaperManagerServiceTests {
|
|||||||
assertEquals(systemWallpaperData.primaryColors, shouldMatchSystem.primaryColors);
|
assertEquals(systemWallpaperData.primaryColors, shouldMatchSystem.primaryColors);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testWallpaperManagerCallbackInRightOrder() throws RemoteException {
|
||||||
|
WallpaperData wallpaper = new WallpaperData(
|
||||||
|
USER_SYSTEM, mService.getWallpaperDir(USER_SYSTEM), WALLPAPER, WALLPAPER_CROP);
|
||||||
|
wallpaper.primaryColors = new WallpaperColors(Color.valueOf(Color.RED),
|
||||||
|
Color.valueOf(Color.BLUE), null);
|
||||||
|
|
||||||
|
spyOn(wallpaper);
|
||||||
|
doReturn(wallpaper).when(mService).getWallpaperSafeLocked(wallpaper.userId, FLAG_SYSTEM);
|
||||||
|
doNothing().when(mService).switchWallpaper(any(), any());
|
||||||
|
doReturn(true).when(mService)
|
||||||
|
.bindWallpaperComponentLocked(any(), anyBoolean(), anyBoolean(), any(), any());
|
||||||
|
doNothing().when(mService).saveSettingsLocked(wallpaper.userId);
|
||||||
|
doNothing().when(mService).generateCrop(wallpaper);
|
||||||
|
|
||||||
|
// timestamps of {ACTION_WALLPAPER_CHANGED, onWallpaperColorsChanged}
|
||||||
|
final long[] timestamps = new long[2];
|
||||||
|
doAnswer(invocation -> timestamps[0] = SystemClock.elapsedRealtime())
|
||||||
|
.when(sContext).sendBroadcastAsUser(any(), any());
|
||||||
|
doAnswer(invocation -> timestamps[1] = SystemClock.elapsedRealtime())
|
||||||
|
.when(mService).notifyWallpaperColorsChanged(wallpaper, FLAG_SYSTEM);
|
||||||
|
|
||||||
|
assertNull(wallpaper.wallpaperObserver);
|
||||||
|
mService.switchUser(wallpaper.userId, null);
|
||||||
|
assertNotNull(wallpaper.wallpaperObserver);
|
||||||
|
// We will call onEvent directly, so stop watching the file.
|
||||||
|
wallpaper.wallpaperObserver.stopWatching();
|
||||||
|
|
||||||
|
spyOn(wallpaper.wallpaperObserver);
|
||||||
|
doReturn(wallpaper).when(wallpaper.wallpaperObserver).dataForEvent(true, false);
|
||||||
|
wallpaper.wallpaperObserver.onEvent(CLOSE_WRITE, WALLPAPER);
|
||||||
|
|
||||||
|
// ACTION_WALLPAPER_CHANGED should be invoked before onWallpaperColorsChanged.
|
||||||
|
assertTrue(timestamps[1] > timestamps[0]);
|
||||||
|
}
|
||||||
|
|
||||||
// Verify that after continue switch user from userId 0 to lastUserId, the wallpaper data for
|
// Verify that after continue switch user from userId 0 to lastUserId, the wallpaper data for
|
||||||
// non-current user must not bind to wallpaper service.
|
// non-current user must not bind to wallpaper service.
|
||||||
private void verifyNoConnectionBeforeLastUser(int lastUserId) {
|
private void verifyNoConnectionBeforeLastUser(int lastUserId) {
|
||||||
|
|||||||
Reference in New Issue
Block a user