Support wallpaper on secondary displays.(7/N)

Expand the wallpaper color listener for multiple displays. This will
allow the launcher on the secondary display can also receive the
correct wallpaper color.

Bug: 115486823
Test: atest WallpaperManagerTest
Test: atest ActivityManagerMultiDisplayTests
Change-Id: I3d893537a8c606170b5641c9eb4683d09743d80c
This commit is contained in:
wilsonshih
2018-12-05 18:56:39 +08:00
parent d97e904c8a
commit 36597d4bd7
5 changed files with 155 additions and 60 deletions

View File

@@ -142,19 +142,20 @@ interface IWallpaperManager {
*
* @param which either {@link WallpaperManager#FLAG_LOCK}
* or {@link WallpaperManager#FLAG_SYSTEM}
* @param displayId Which display is interested
* @return colors of chosen wallpaper
*/
WallpaperColors getWallpaperColors(int which, int userId);
WallpaperColors getWallpaperColors(int which, int userId, int displayId);
/**
* Register a callback to receive color updates
* Register a callback to receive color updates from a display
*/
void registerWallpaperColorsCallback(IWallpaperManagerCallback cb, int userId);
void registerWallpaperColorsCallback(IWallpaperManagerCallback cb, int userId, int displayId);
/**
* Unregister a callback that was receiving color updates
* Unregister a callback that was receiving color updates from a display
*/
void unregisterWallpaperColorsCallback(IWallpaperManagerCallback cb, int userId);
void unregisterWallpaperColorsCallback(IWallpaperManagerCallback cb, int userId, int displayId);
/**
* Called from SystemUI when it shows the AoD UI.

View File

@@ -307,13 +307,14 @@ public class WallpaperManager {
* @param callback Listener
* @param handler Thread to call it from. Main thread if null.
* @param userId Owner of the wallpaper or UserHandle.USER_ALL
* @param displayId Caller comes from which display
*/
public void addOnColorsChangedListener(@NonNull OnColorsChangedListener callback,
@Nullable Handler handler, int userId) {
@Nullable Handler handler, int userId, int displayId) {
synchronized (this) {
if (!mColorCallbackRegistered) {
try {
mService.registerWallpaperColorsCallback(this, userId);
mService.registerWallpaperColorsCallback(this, userId, displayId);
mColorCallbackRegistered = true;
} catch (RemoteException e) {
// Failed, service is gone
@@ -329,16 +330,17 @@ public class WallpaperManager {
*
* @param callback listener
* @param userId Owner of the wallpaper or UserHandle.USER_ALL
* @param displayId Which display is interested
*/
public void removeOnColorsChangedListener(@NonNull OnColorsChangedListener callback,
int userId) {
int userId, int displayId) {
synchronized (this) {
mColorListeners.removeIf(pair -> pair.first == callback);
if (mColorListeners.size() == 0 && mColorCallbackRegistered) {
mColorCallbackRegistered = false;
try {
mService.unregisterWallpaperColorsCallback(this, userId);
mService.unregisterWallpaperColorsCallback(this, userId, displayId);
} catch (RemoteException e) {
// Failed, service is gone
Log.w(TAG, "Can't unregister color updates", e);
@@ -370,14 +372,14 @@ public class WallpaperManager {
}
}
WallpaperColors getWallpaperColors(int which, int userId) {
WallpaperColors getWallpaperColors(int which, int userId, int displayId) {
if (which != FLAG_LOCK && which != FLAG_SYSTEM) {
throw new IllegalArgumentException(
"Must request colors for exactly one kind of wallpaper");
}
try {
return mService.getWallpaperColors(which, userId);
return mService.getWallpaperColors(which, userId, displayId);
} catch (RemoteException e) {
// Can't get colors, connection lost.
}
@@ -894,7 +896,7 @@ public class WallpaperManager {
@UnsupportedAppUsage
public void addOnColorsChangedListener(@NonNull OnColorsChangedListener listener,
@NonNull Handler handler, int userId) {
sGlobals.addOnColorsChangedListener(listener, handler, userId);
sGlobals.addOnColorsChangedListener(listener, handler, userId, mContext.getDisplayId());
}
/**
@@ -913,7 +915,7 @@ public class WallpaperManager {
*/
public void removeOnColorsChangedListener(@NonNull OnColorsChangedListener callback,
int userId) {
sGlobals.removeOnColorsChangedListener(callback, userId);
sGlobals.removeOnColorsChangedListener(callback, userId, mContext.getDisplayId());
}
/**
@@ -947,7 +949,7 @@ public class WallpaperManager {
*/
@UnsupportedAppUsage
public @Nullable WallpaperColors getWallpaperColors(int which, int userId) {
return sGlobals.getWallpaperColors(which, userId);
return sGlobals.getWallpaperColors(which, userId, mContext.getDisplayId());
}
/**

View File

@@ -27,5 +27,5 @@ interface IWallpaperConnection {
void attachEngine(IWallpaperEngine engine, int displayId);
void engineShown(IWallpaperEngine engine);
ParcelFileDescriptor setWallpaper(String name);
void onWallpaperColorsChanged(in WallpaperColors colors);
void onWallpaperColorsChanged(in WallpaperColors colors, int displayId);
}

View File

@@ -641,7 +641,7 @@ public abstract class WallpaperService extends Service {
try {
final WallpaperColors newColors = onComputeColors();
if (mConnection != null) {
mConnection.onWallpaperColorsChanged(newColors);
mConnection.onWallpaperColorsChanged(newColors, mDisplay.getDisplayId());
} else {
Log.w(TAG, "Can't notify system because wallpaper connection "
+ "was not established.");
@@ -1465,7 +1465,7 @@ public abstract class WallpaperService extends Service {
break;
}
try {
mConnection.onWallpaperColorsChanged(mEngine.onComputeColors());
mConnection.onWallpaperColorsChanged(mEngine.onComputeColors(), mDisplayId);
} catch (RemoteException e) {
// Connection went away, nothing to do in here.
}

View File

@@ -350,12 +350,34 @@ public class WallpaperManagerService extends IWallpaperManager.Stub
}
private void notifyWallpaperColorsChanged(@NonNull WallpaperData wallpaper, int which) {
if (wallpaper.connection != null) {
wallpaper.connection.forEachDisplayConnector(connector -> {
notifyWallpaperColorsChangedOnDisplay(wallpaper, which, connector.mDisplayId);
});
} else { // Lock wallpaper does not have WallpaperConnection.
notifyWallpaperColorsChangedOnDisplay(wallpaper, which, DEFAULT_DISPLAY);
}
}
private RemoteCallbackList<IWallpaperManagerCallback> getWallpaperCallbacks(int userId,
int displayId) {
RemoteCallbackList<IWallpaperManagerCallback> listeners = null;
final SparseArray<RemoteCallbackList<IWallpaperManagerCallback>> displayListeners =
mColorsChangedListeners.get(userId);
if (displayListeners != null) {
listeners = displayListeners.get(displayId);
}
return listeners;
}
private void notifyWallpaperColorsChangedOnDisplay(@NonNull WallpaperData wallpaper, int which,
int displayId) {
boolean needsExtraction;
synchronized (mLock) {
final RemoteCallbackList<IWallpaperManagerCallback> currentUserColorListeners =
mColorsChangedListeners.get(wallpaper.userId);
getWallpaperCallbacks(wallpaper.userId, displayId);
final RemoteCallbackList<IWallpaperManagerCallback> userAllColorListeners =
mColorsChangedListeners.get(UserHandle.USER_ALL);
getWallpaperCallbacks(UserHandle.USER_ALL, displayId);
// No-op until someone is listening to it.
if (emptyCallbackList(currentUserColorListeners) &&
emptyCallbackList(userAllColorListeners)) {
@@ -363,7 +385,7 @@ public class WallpaperManagerService extends IWallpaperManager.Stub
}
if (DEBUG) {
Slog.v(TAG, "notifyWallpaperColorsChanged " + which);
Slog.v(TAG, "notifyWallpaperColorsChangedOnDisplay " + which);
}
needsExtraction = wallpaper.primaryColors == null;
@@ -371,7 +393,7 @@ public class WallpaperManagerService extends IWallpaperManager.Stub
// Let's notify the current values, it's fine if it's null, it just means
// that we don't know yet.
notifyColorListeners(wallpaper.primaryColors, which, wallpaper.userId);
notifyColorListeners(wallpaper.primaryColors, which, wallpaper.userId, displayId);
if (needsExtraction) {
extractColors(wallpaper);
@@ -381,7 +403,7 @@ public class WallpaperManagerService extends IWallpaperManager.Stub
return;
}
}
notifyColorListeners(wallpaper.primaryColors, which, wallpaper.userId);
notifyColorListeners(wallpaper.primaryColors, which, wallpaper.userId, displayId);
}
}
@@ -390,14 +412,14 @@ public class WallpaperManagerService extends IWallpaperManager.Stub
}
private void notifyColorListeners(@NonNull WallpaperColors wallpaperColors, int which,
int userId) {
int userId, int displayId) {
final IWallpaperManagerCallback keyguardListener;
final ArrayList<IWallpaperManagerCallback> colorListeners = new ArrayList<>();
synchronized (mLock) {
final RemoteCallbackList<IWallpaperManagerCallback> currentUserColorListeners =
mColorsChangedListeners.get(userId);
getWallpaperCallbacks(userId, displayId);
final RemoteCallbackList<IWallpaperManagerCallback> userAllColorListeners =
mColorsChangedListeners.get(UserHandle.USER_ALL);
getWallpaperCallbacks(UserHandle.USER_ALL, displayId);
keyguardListener = mKeyguardListener;
if (currentUserColorListeners != null) {
@@ -427,7 +449,8 @@ public class WallpaperManagerService extends IWallpaperManager.Stub
}
}
if (keyguardListener != null) {
// Only shows Keyguard on default display
if (keyguardListener != null && displayId == DEFAULT_DISPLAY) {
try {
keyguardListener.onWallpaperColorsChanged(wallpaperColors, which, userId);
} catch (RemoteException e) {
@@ -446,6 +469,11 @@ public class WallpaperManagerService extends IWallpaperManager.Stub
String cropFile = null;
int wallpaperId;
if (wallpaper.equals(mFallbackWallpaper)) {
extractDefaultImageWallpaperColors();
return;
}
synchronized (mLock) {
// Not having a wallpaperComponent means it's a lock screen wallpaper.
final boolean imageWallpaper = mImageWallpaper.equals(wallpaper.wallpaperComponent)
@@ -482,6 +510,39 @@ public class WallpaperManagerService extends IWallpaperManager.Stub
}
}
private void extractDefaultImageWallpaperColors() {
synchronized (mLock) {
if (mFallbackWallpaper.primaryColors != null) return;
}
if (DEBUG) Slog.d(TAG, "Extract default image wallpaper colors");
WallpaperColors colors = null;
final InputStream is = WallpaperManager.openDefaultWallpaper(mContext, FLAG_SYSTEM);
if (is != null) {
try {
final BitmapFactory.Options options = new BitmapFactory.Options();
final Bitmap bitmap = BitmapFactory.decodeStream(is, null, options);
if (bitmap != null) {
colors = WallpaperColors.fromBitmap(bitmap);
bitmap.recycle();
}
} catch (OutOfMemoryError e) {
Slog.w(TAG, "Can't decode default wallpaper stream", e);
} finally {
IoUtils.closeQuietly(is);
}
}
if (colors == null) {
Slog.e(TAG, "Extract default image wallpaper colors failed");
return;
}
synchronized (mLock) {
mFallbackWallpaper.primaryColors = colors;
}
}
/**
* Once a new wallpaper has been written via setWallpaper(...), it needs to be cropped
* for display.
@@ -696,6 +757,11 @@ public class WallpaperManagerService extends IWallpaperManager.Stub
targetWallpaper.connection.removeDisplayConnector(displayId);
removeDisplayData(displayId);
}
for (int i = mColorsChangedListeners.size() - 1; i >= 0; i--) {
final SparseArray<RemoteCallbackList<IWallpaperManagerCallback>> callbacks =
mColorsChangedListeners.valueAt(i);
callbacks.delete(displayId);
}
}
}
@@ -706,9 +772,11 @@ public class WallpaperManagerService extends IWallpaperManager.Stub
/**
* Map of color listeners per user id.
* The key will be the id of a user or UserHandle.USER_ALL - for wildcard listeners.
* The first key will be the id of a user or UserHandle.USER_ALL - for wildcard listeners.
* The secondary key will be the display id, which means which display the listener is
* interested in.
*/
private final SparseArray<RemoteCallbackList<IWallpaperManagerCallback>>
private final SparseArray<SparseArray<RemoteCallbackList<IWallpaperManagerCallback>>>
mColorsChangedListeners;
private WallpaperData mLastWallpaper;
private IWallpaperManagerCallback mKeyguardListener;
@@ -1228,9 +1296,10 @@ public class WallpaperManagerService extends IWallpaperManager.Stub
/**
* Called by a live wallpaper if its colors have changed.
* @param primaryColors representation of wallpaper primary colors
* @param displayId for which display
*/
@Override
public void onWallpaperColorsChanged(WallpaperColors primaryColors) {
public void onWallpaperColorsChanged(WallpaperColors primaryColors, int displayId) {
int which;
synchronized (mLock) {
// Do not broadcast changes on ImageWallpaper since it's handled
@@ -1243,14 +1312,16 @@ public class WallpaperManagerService extends IWallpaperManager.Stub
// Live wallpapers always are system wallpapers.
which = FLAG_SYSTEM;
// It's also the lock screen wallpaper when we don't have a bitmap in there
WallpaperData lockedWallpaper = mLockWallpaperMap.get(mWallpaper.userId);
if (lockedWallpaper == null) {
which |= FLAG_LOCK;
// It's also the lock screen wallpaper when we don't have a bitmap in there.
if (displayId == DEFAULT_DISPLAY) {
final WallpaperData lockedWallpaper = mLockWallpaperMap.get(mWallpaper.userId);
if (lockedWallpaper == null) {
which |= FLAG_LOCK;
}
}
}
if (which != 0) {
notifyWallpaperColorsChanged(mWallpaper, which);
notifyWallpaperColorsChangedOnDisplay(mWallpaper, which, displayId);
}
}
@@ -1277,16 +1348,12 @@ public class WallpaperManagerService extends IWallpaperManager.Stub
Slog.w(TAG, "Failed to set ambient mode state", e);
}
}
// TODO(multi-display) So far, we have shared the same wallpaper on each display.
// Once we have multiple wallpapers on multiple displays, please complete here.
if (displayId == DEFAULT_DISPLAY) {
try {
// This will trigger onComputeColors in the wallpaper engine.
// It's fine to be locked in here since the binder is oneway.
connector.mEngine.requestWallpaperColors();
} catch (RemoteException e) {
Slog.w(TAG, "Failed to request wallpaper colors", e);
}
try {
// This will trigger onComputeColors in the wallpaper engine.
// It's fine to be locked in here since the binder is oneway.
connector.mEngine.requestWallpaperColors();
} catch (RemoteException e) {
Slog.w(TAG, "Failed to request wallpaper colors", e);
}
}
}
@@ -1681,6 +1748,7 @@ public class WallpaperManagerService extends IWallpaperManager.Stub
FgThread.getHandler().post(() -> {
notifyWallpaperColorsChanged(systemWallpaper, FLAG_SYSTEM);
notifyWallpaperColorsChanged(lockWallpaper, FLAG_LOCK);
notifyWallpaperColorsChanged(mFallbackWallpaper, FLAG_SYSTEM);
});
}
@@ -1743,6 +1811,7 @@ public class WallpaperManagerService extends IWallpaperManager.Stub
// When clearing a wallpaper, broadcast new valid colors
if (data != null) {
notifyWallpaperColorsChanged(data, which);
notifyWallpaperColorsChanged(mFallbackWallpaper, FLAG_SYSTEM);
}
}
@@ -2084,35 +2153,47 @@ public class WallpaperManagerService extends IWallpaperManager.Stub
}
@Override
public void registerWallpaperColorsCallback(IWallpaperManagerCallback cb, int userId) {
public void registerWallpaperColorsCallback(IWallpaperManagerCallback cb, int userId,
int displayId) {
userId = ActivityManager.handleIncomingUser(Binder.getCallingPid(), Binder.getCallingUid(),
userId, true, true, "registerWallpaperColorsCallback", null);
synchronized (mLock) {
RemoteCallbackList<IWallpaperManagerCallback> userColorsChangedListeners =
mColorsChangedListeners.get(userId);
if (userColorsChangedListeners == null) {
userColorsChangedListeners = new RemoteCallbackList<>();
mColorsChangedListeners.put(userId, userColorsChangedListeners);
SparseArray<RemoteCallbackList<IWallpaperManagerCallback>>
userDisplayColorsChangedListeners = mColorsChangedListeners.get(userId);
if (userDisplayColorsChangedListeners == null) {
userDisplayColorsChangedListeners = new SparseArray<>();
mColorsChangedListeners.put(userId, userDisplayColorsChangedListeners);
}
userColorsChangedListeners.register(cb);
RemoteCallbackList<IWallpaperManagerCallback> displayChangedListeners =
userDisplayColorsChangedListeners.get(displayId);
if (displayChangedListeners == null) {
displayChangedListeners = new RemoteCallbackList<>();
userDisplayColorsChangedListeners.put(displayId, displayChangedListeners);
}
displayChangedListeners.register(cb);
}
}
@Override
public void unregisterWallpaperColorsCallback(IWallpaperManagerCallback cb, int userId) {
public void unregisterWallpaperColorsCallback(IWallpaperManagerCallback cb, int userId,
int displayId) {
userId = ActivityManager.handleIncomingUser(Binder.getCallingPid(), Binder.getCallingUid(),
userId, true, true, "unregisterWallpaperColorsCallback", null);
synchronized (mLock) {
final RemoteCallbackList<IWallpaperManagerCallback> userColorsChangedListeners =
mColorsChangedListeners.get(userId);
if (userColorsChangedListeners != null) {
userColorsChangedListeners.unregister(cb);
SparseArray<RemoteCallbackList<IWallpaperManagerCallback>>
userDisplayColorsChangedListeners = mColorsChangedListeners.get(userId);
if (userDisplayColorsChangedListeners != null) {
RemoteCallbackList<IWallpaperManagerCallback> displayChangedListeners =
userDisplayColorsChangedListeners.get(displayId);
if (displayChangedListeners != null) {
displayChangedListeners.unregister(cb);
}
}
}
}
/**
* TODO(b/115486823) Extends this method with specific display.
* TODO(multi-display) Extends this method with specific display.
* Propagate ambient state to wallpaper engine.
*
* @param inAmbientMode {@code true} when in ambient mode, {@code false} otherwise.
@@ -2125,7 +2206,7 @@ public class WallpaperManagerService extends IWallpaperManager.Stub
final WallpaperData data = mWallpaperMap.get(mCurrentUserId);
if (data != null && data.connection != null && data.connection.mInfo != null
&& data.connection.mInfo.supportsAmbientMode()) {
// TODO(b/115486823) Extends this method with specific display.
// TODO(multi-display) Extends this method with specific display.
engine = data.connection.getDisplayConnectorOrCreate(DEFAULT_DISPLAY).mEngine;
} else {
engine = null;
@@ -2151,7 +2232,8 @@ public class WallpaperManagerService extends IWallpaperManager.Stub
}
@Override
public WallpaperColors getWallpaperColors(int which, int userId) throws RemoteException {
public WallpaperColors getWallpaperColors(int which, int userId, int displayId)
throws RemoteException {
if (which != FLAG_LOCK && which != FLAG_SYSTEM) {
throw new IllegalArgumentException("which should be either FLAG_LOCK or FLAG_SYSTEM");
}
@@ -2169,7 +2251,7 @@ public class WallpaperManagerService extends IWallpaperManager.Stub
// Try to get the system wallpaper anyway since it might
// also be the lock screen wallpaper
if (wallpaperData == null) {
wallpaperData = mWallpaperMap.get(userId);
wallpaperData = findWallpaperAtDisplay(userId, displayId);
}
if (wallpaperData == null) {
@@ -2187,6 +2269,15 @@ public class WallpaperManagerService extends IWallpaperManager.Stub
}
}
private WallpaperData findWallpaperAtDisplay(int userId, int displayId) {
if (mFallbackWallpaper != null && mFallbackWallpaper.connection != null
&& mFallbackWallpaper.connection.containsDisplay(displayId)) {
return mFallbackWallpaper;
} else {
return mWallpaperMap.get(userId);
}
}
@Override
public ParcelFileDescriptor setWallpaper(String name, String callingPackage,
Rect cropHint, boolean allowBackup, Bundle extras, int which,
@@ -2382,6 +2473,7 @@ public class WallpaperManagerService extends IWallpaperManager.Stub
if (shouldNotifyColors) {
notifyWallpaperColorsChanged(wallpaper, which);
notifyWallpaperColorsChanged(mFallbackWallpaper, FLAG_SYSTEM);
}
}