Merge "Wallpaper color extraction"

This commit is contained in:
Lucas Dupin
2017-04-27 22:08:09 +00:00
committed by Android (Google) Code Review
10 changed files with 465 additions and 11 deletions

View File

@@ -22,6 +22,7 @@ import android.os.ParcelFileDescriptor;
import android.app.IWallpaperManagerCallback;
import android.app.WallpaperInfo;
import android.content.ComponentName;
import android.app.WallpaperColors;
/** @hide */
interface IWallpaperManager {
@@ -135,4 +136,23 @@ interface IWallpaperManager {
* wallpaper content has changed.
*/
boolean setLockWallpaperCallback(IWallpaperManagerCallback cb);
/**
* Returns the colors used by the lock screen or system wallpaper.
*
* @param which either {@link WallpaperManager#FLAG_LOCK}
* or {@link WallpaperManager#FLAG_SYSTEM}
* @return colors of chosen wallpaper
*/
WallpaperColors getWallpaperColors(int which);
/**
* Register a callback to receive color updates
*/
void registerWallpaperColorsCallback(IWallpaperManagerCallback cb);
/**
* Unregister a callback that was receiving color updates
*/
void unregisterWallpaperColorsCallback(IWallpaperManagerCallback cb);
}

View File

@@ -16,6 +16,8 @@
package android.app;
import android.app.WallpaperColors;
/**
* Callback interface used by IWallpaperManager to send asynchronous
* notifications back to its clients. Note that this is a
@@ -28,4 +30,10 @@ oneway interface IWallpaperManagerCallback {
* Called when the wallpaper has changed
*/
void onWallpaperChanged();
/**
* Called when wallpaper colors change
*/
void onWallpaperColorsChanged(in WallpaperColors colors, int which);
}

View File

@@ -0,0 +1,19 @@
/*
* 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 android.app;
parcelable WallpaperColors;

View File

@@ -22,6 +22,7 @@ import android.os.Parcelable;
import android.util.Pair;
import java.util.ArrayList;
import java.util.List;
/**
@@ -29,7 +30,19 @@ import java.util.List;
*/
public final class WallpaperColors implements Parcelable {
private static final float BRIGHT_LUMINANCE = 0.9f;
private final List<Pair<Color, Integer>> mColors;
private final boolean mSupportsDarkText;
public WallpaperColors(Parcel parcel) {
mColors = new ArrayList<>();
int count = parcel.readInt();
for (int i=0; i < count; i++) {
Color color = Color.valueOf(parcel.readInt());
int weight = parcel.readInt();
mColors.add(new Pair<>(color, weight));
}
mSupportsDarkText = parcel.readBoolean();
}
/**
@@ -43,6 +56,7 @@ public final class WallpaperColors implements Parcelable {
* and number of occurrences/influence.
*/
public WallpaperColors(List<Pair<Color, Integer>> colors) {
this(colors, calculateDarkTextSupport(colors));
}
/**
@@ -55,6 +69,10 @@ public final class WallpaperColors implements Parcelable {
* @param supportsDarkText can have dark text on top or not
*/
public WallpaperColors(List<Pair<Color, Integer>> colors, boolean supportsDarkText) {
if (colors == null)
colors = new ArrayList<>();
mColors = colors;
mSupportsDarkText = supportsDarkText;
}
public static final Creator<WallpaperColors> CREATOR = new Creator<WallpaperColors>() {
@@ -76,6 +94,13 @@ public final class WallpaperColors implements Parcelable {
@Override
public void writeToParcel(Parcel dest, int flags) {
int count = mColors.size();
dest.writeInt(count);
for (Pair<Color, Integer> color : mColors) {
dest.writeInt(color.first.toArgb());
dest.writeInt(color.second);
}
dest.writeBoolean(mSupportsDarkText);
}
/**
@@ -83,7 +108,22 @@ public final class WallpaperColors implements Parcelable {
* @return list of colors paired with their weights.
*/
public List<Pair<Color, Integer>> getColors() {
return null;
return mColors;
}
@Override
public boolean equals(Object o) {
if (o == null || getClass() != o.getClass()) {
return false;
}
WallpaperColors other = (WallpaperColors) o;
return mColors.equals(other.mColors) && mSupportsDarkText == other.mSupportsDarkText;
}
@Override
public int hashCode() {
return 31 * mColors.hashCode() + (mSupportsDarkText ? 1 : 0);
}
/**
@@ -92,6 +132,24 @@ public final class WallpaperColors implements Parcelable {
* @return true if dark text is supported
*/
public boolean supportsDarkText() {
return false;
return mSupportsDarkText;
}
private static boolean calculateDarkTextSupport(List<Pair<Color, Integer>> colors) {
if (colors == null) {
return false;
}
Pair<Color, Integer> mainColor = null;
for (Pair<Color, Integer> color : colors) {
if (mainColor == null) {
mainColor = color;
} else if (color.second > mainColor.second) {
mainColor = color;
}
}
return mainColor != null &&
mainColor.first.luminance() > BRIGHT_LUMINANCE;
}
}

View File

@@ -52,13 +52,13 @@ import android.os.Handler;
import android.os.IBinder;
import android.os.Looper;
import android.os.ParcelFileDescriptor;
import android.os.Process;
import android.os.RemoteException;
import android.os.ServiceManager;
import android.os.SystemProperties;
import android.os.UserHandle;
import android.text.TextUtils;
import android.util.Log;
import android.util.Pair;
import android.view.WindowManagerGlobal;
import libcore.io.IoUtils;
@@ -71,6 +71,8 @@ import java.io.IOException;
import java.io.InputStream;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
@@ -271,15 +273,20 @@ public class WallpaperManager {
}
}
static class Globals extends IWallpaperManagerCallback.Stub {
private static class Globals extends IWallpaperManagerCallback.Stub {
private final IWallpaperManager mService;
private boolean mColorCallbackRegistered;
private final ArrayList<Pair<OnColorsChangedListener, Handler>> mColorListeners =
new ArrayList<>();
private Bitmap mCachedWallpaper;
private int mCachedWallpaperUserId;
private Bitmap mDefaultWallpaper;
private Handler mMainLooperHandler;
Globals(Looper looper) {
IBinder b = ServiceManager.getService(Context.WALLPAPER_SERVICE);
mService = IWallpaperManager.Stub.asInterface(b);
mMainLooperHandler = new Handler(looper);
forgetLoadedWallpaper();
}
@@ -292,6 +299,88 @@ public class WallpaperManager {
forgetLoadedWallpaper();
}
/**
* Start listening to wallpaper color events.
* Will be called whenever someone changes their wallpaper or if a live wallpaper
* changes its colors.
* @param callback Listener
* @param handler Thread to call it from. Main thread if null.
*/
public void addOnColorsChangedListener(@NonNull OnColorsChangedListener callback,
@Nullable Handler handler) {
synchronized (this) {
if (!mColorCallbackRegistered) {
try {
mService.registerWallpaperColorsCallback(this);
mColorCallbackRegistered = true;
} catch (RemoteException e) {
// Failed, service is gone
Log.w(TAG, "Can't register for color updates", e);
}
}
mColorListeners.add(new Pair<>(callback, handler));
}
}
/**
* Stop listening to wallpaper color events.
*
* @param callback listener
*/
public void removeOnColorsChangedListener(@NonNull OnColorsChangedListener callback) {
synchronized (this) {
mColorListeners.removeIf(pair -> pair.first == callback);
if (mColorListeners.size() == 0 && mColorCallbackRegistered) {
mColorCallbackRegistered = false;
try {
mService.unregisterWallpaperColorsCallback(this);
} catch (RemoteException e) {
// Failed, service is gone
Log.w(TAG, "Can't unregister color updates", e);
}
}
}
}
@Override
public void onWallpaperColorsChanged(WallpaperColors colors, int which) {
synchronized (this) {
for (Pair<OnColorsChangedListener, Handler> listener : mColorListeners) {
Handler handler = listener.second;
if (listener.second == null) {
handler = mMainLooperHandler;
}
handler.post(() -> {
// Dealing with race conditions between posting a callback and
// removeOnColorsChangedListener being called.
boolean stillExists;
synchronized (sGlobals) {
stillExists = mColorListeners.contains(listener);
}
if (stillExists) {
listener.first.onColorsChanged(colors, which);
}
});
}
}
}
WallpaperColors getWallpaperColors(int which) {
synchronized (this) {
if (which != FLAG_LOCK && which != FLAG_SYSTEM)
throw new IllegalArgumentException(
"which should be either FLAG_LOCK or FLAG_SYSTEM");
try {
return mService.getWallpaperColors(which);
} catch (RemoteException e) {
// Can't get colors, connection lost.
}
return null;
}
}
public Bitmap peekWallpaperBitmap(Context context, boolean returnDefault,
@SetWallpaperFlags int which) {
return peekWallpaperBitmap(context, returnDefault, which, context.getUserId());
@@ -746,7 +835,6 @@ public class WallpaperManager {
return getWallpaperFile(which, mContext.getUserId());
}
/**
* Registers a listener to get notified when the wallpaper colors change.
* Callback might be called from an arbitrary background thread.
@@ -754,16 +842,18 @@ public class WallpaperManager {
* @param listener A listener to register
*/
public void addOnColorsChangedListener(@NonNull OnColorsChangedListener listener) {
sGlobals.addOnColorsChangedListener(listener, null);
}
/**
* Registers a listener to get notified when the wallpaper colors change
* @param listener A listener to register
* @param handler Where to call it from. Might be called from a background thread
* @param handler Where to call it from. Will be called from the main thread
* if null.
*/
public void addOnColorsChangedListener(@NonNull OnColorsChangedListener listener,
@Nullable Handler handler) {
@NonNull Handler handler) {
sGlobals.addOnColorsChangedListener(listener, handler);
}
/**
@@ -771,6 +861,7 @@ public class WallpaperManager {
* @param callback A callback to unsubscribe
*/
public void removeOnColorsChangedListener(@NonNull OnColorsChangedListener callback) {
sGlobals.removeOnColorsChangedListener(callback);
}
/**
@@ -780,7 +871,7 @@ public class WallpaperManager {
* @return a list of colors ordered by priority
*/
public @Nullable WallpaperColors getWallpaperColors(int which) {
return null;
return sGlobals.getWallpaperColors(which);
}
/**
@@ -1773,6 +1864,12 @@ public class WallpaperManager {
public void onWallpaperChanged() throws RemoteException {
mLatch.countDown();
}
@Override
public void onWallpaperColorsChanged(WallpaperColors colors, int which)
throws RemoteException {
sGlobals.onWallpaperColorsChanged(colors, which);
}
}
/**

View File

@@ -18,6 +18,7 @@ package android.service.wallpaper;
import android.os.ParcelFileDescriptor;
import android.service.wallpaper.IWallpaperEngine;
import android.app.WallpaperColors;
/**
* @hide
@@ -26,4 +27,5 @@ interface IWallpaperConnection {
void attachEngine(IWallpaperEngine engine);
void engineShown(IWallpaperEngine engine);
ParcelFileDescriptor setWallpaper(String name);
void onWallpaperColorsChanged(in WallpaperColors colors);
}

View File

@@ -30,5 +30,5 @@ oneway interface IWallpaperEngine {
void dispatchPointer(in MotionEvent event);
void dispatchWallpaperCommand(String action, int x, int y,
int z, in Bundle extras);
void destroy();
void destroy();
}

View File

@@ -550,6 +550,12 @@ public abstract class WallpaperService extends Service {
* This will trigger a {@link #onComputeWallpaperColors()} call.
*/
public void invalidateColors() {
try {
mConnection.onWallpaperColorsChanged(onComputeWallpaperColors());
} catch (RemoteException e) {
Log.w(TAG, "Can't invalidate wallpaper colors because " +
"wallpaper connection was lost", e);
}
}
/**
@@ -562,7 +568,7 @@ public abstract class WallpaperService extends Service {
public @Nullable WallpaperColors onComputeWallpaperColors() {
return null;
}
protected void dump(String prefix, FileDescriptor fd, PrintWriter out, String[] args) {
out.print(prefix); out.print("mInitializing="); out.print(mInitializing);
out.print(" mDestroyed="); out.println(mDestroyed);
@@ -1199,6 +1205,7 @@ public abstract class WallpaperService extends Service {
mEngine = engine;
mActiveEngines.add(engine);
engine.attach(this);
engine.invalidateColors();
return;
}
case DO_DETACH: {

View File

@@ -36,6 +36,7 @@ import android.os.ParcelFileDescriptor;
import android.os.RemoteException;
import android.os.ServiceManager;
import android.os.UserHandle;
import android.app.WallpaperColors;
import android.util.Log;
import com.android.keyguard.KeyguardUpdateMonitor;
@@ -156,6 +157,11 @@ public class LockscreenWallpaper extends IWallpaperManagerCallback.Stub implemen
postUpdateWallpaper();
}
@Override
public void onWallpaperColorsChanged(WallpaperColors colors, int which) {
}
private void postUpdateWallpaper() {
mH.removeCallbacks(this);
mH.post(this);

View File

@@ -52,6 +52,7 @@ import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.BitmapRegionDecoder;
import android.graphics.Color;
import android.graphics.Point;
import android.graphics.Rect;
import android.os.Binder;
@@ -73,10 +74,12 @@ import android.os.UserManager;
import android.service.wallpaper.IWallpaperConnection;
import android.service.wallpaper.IWallpaperEngine;
import android.service.wallpaper.IWallpaperService;
import android.app.WallpaperColors;
import android.service.wallpaper.WallpaperService;
import android.system.ErrnoException;
import android.system.Os;
import android.util.EventLog;
import android.util.Pair;
import android.util.Slog;
import android.util.SparseArray;
import android.util.Xml;
@@ -86,6 +89,7 @@ import android.view.WindowManager;
import com.android.internal.R;
import com.android.internal.content.PackageMonitor;
import com.android.internal.graphics.palette.Palette;
import com.android.internal.os.BackgroundThread;
import com.android.internal.util.DumpUtils;
import com.android.internal.util.FastXmlSerializer;
@@ -94,6 +98,7 @@ import com.android.server.EventLogTags;
import com.android.server.FgThread;
import com.android.server.SystemService;
import java.util.ArrayList;
import libcore.io.IoUtils;
import org.xmlpull.v1.XmlPullParser;
@@ -219,6 +224,7 @@ public class WallpaperManagerService extends IWallpaperManager.Stub {
// lock-only changes happen on the dedicated lock wallpaper input file
final boolean sysWallpaperChanged = (mWallpaperFile.equals(changedFile));
final boolean lockWallpaperChanged = (mWallpaperLockFile.equals(changedFile));
int notifyColorsWhich = 0;
WallpaperData wallpaper = dataForEvent(sysWallpaperChanged, lockWallpaperChanged);
if (DEBUG) {
@@ -240,6 +246,7 @@ public class WallpaperManagerService extends IWallpaperManager.Stub {
}
SELinux.restorecon(changedFile);
notifyLockWallpaperChanged();
notifyWallpaperColorsChanged(wallpaper, FLAG_LOCK);
return;
}
@@ -284,6 +291,7 @@ public class WallpaperManagerService extends IWallpaperManager.Stub {
// If this was the system wallpaper, rebind...
bindWallpaperComponentLocked(mImageWallpaper, true,
false, wallpaper, null);
notifyColorsWhich |= FLAG_SYSTEM;
}
if (lockWallpaperChanged
|| (wallpaper.whichPending & FLAG_LOCK) != 0) {
@@ -298,12 +306,19 @@ public class WallpaperManagerService extends IWallpaperManager.Stub {
}
// and in any case, tell keyguard about it
notifyLockWallpaperChanged();
notifyColorsWhich |= FLAG_LOCK;
}
saveSettingsLocked(wallpaper.userId);
}
}
}
}
// Outside of the lock since it will synchronize itself
if (notifyColorsWhich != 0) {
notifyWallpaperColorsChanged(wallpaper, notifyColorsWhich);
}
}
}
@@ -318,6 +333,90 @@ public class WallpaperManagerService extends IWallpaperManager.Stub {
}
}
private void notifyWallpaperColorsChanged(WallpaperData wallpaper, int which) {
boolean needsExtraction;
synchronized (mLock) {
if (mColorsChangedListeners.getRegisteredCallbackCount() == 0)
return;
if (DEBUG) {
Slog.v(TAG, "notifyWallpaperColorsChanged " + which);
}
needsExtraction = wallpaper.primaryColors == null;
}
// This should not be synchronized because color extraction
// might take a while.
if (needsExtraction) {
extractColors(wallpaper);
}
synchronized (mLock) {
final int n = mColorsChangedListeners.beginBroadcast();
for (int i = 0; i < n; i++) {
IWallpaperManagerCallback callback = mColorsChangedListeners.getBroadcastItem(i);
try {
callback.onWallpaperColorsChanged(wallpaper.primaryColors, which);
} catch (RemoteException e) {
// Callback is gone, it's not necessary to unregister it since
// RemoteCallbackList#getBroadcastItem will take care of it.
}
}
mColorsChangedListeners.finishBroadcast();
final IWallpaperManagerCallback cb = mKeyguardListener;
if (cb != null) {
try {
cb.onWallpaperColorsChanged(wallpaper.primaryColors, which);
} catch (RemoteException e) {
// Oh well it went away; no big deal
}
}
}
}
private void extractColors(WallpaperData wallpaper) {
String cropFile = null;
int wallpaperId = -1;
synchronized (mLock) {
// Only extract colors of ImageWallpaper or lock wallpapers (null)
final boolean supportedComponent = mImageWallpaper.equals(wallpaper.wallpaperComponent)
|| wallpaper.wallpaperComponent == null;
if (!supportedComponent)
return;
if (wallpaper.cropFile != null && wallpaper.cropFile.exists()) {
cropFile = wallpaper.cropFile.getAbsolutePath();
}
wallpaperId = wallpaper.wallpaperId;
}
if (cropFile != null) {
final Bitmap bitmap = BitmapFactory.decodeFile(cropFile);
if (bitmap == null) {
Slog.w(TAG, "Cannot extract colors because wallpaper file could not be read.");
return;
}
Palette palette = Palette.from(bitmap).generate();
bitmap.recycle();
final List<Pair<Color, Integer>> colors = new ArrayList<>();
for (Palette.Swatch swatch : palette.getSwatches()) {
colors.add(new Pair<>(Color.valueOf(swatch.getRgb()),
swatch.getPopulation()));
}
synchronized (mLock) {
if (wallpaper.wallpaperId == wallpaperId) {
wallpaper.primaryColors = new WallpaperColors(colors);
} else {
Slog.w(TAG, "Not setting primary colors since wallpaper changed");
}
}
}
}
/**
* Once a new wallpaper has been written via setWallpaper(...), it needs to be cropped
* for display.
@@ -481,6 +580,7 @@ public class WallpaperManagerService extends IWallpaperManager.Stub {
final IPackageManager mIPackageManager;
final MyPackageMonitor mMonitor;
final AppOpsManager mAppOpsManager;
final RemoteCallbackList<IWallpaperManagerCallback> mColorsChangedListeners;
WallpaperData mLastWallpaper;
IWallpaperManagerCallback mKeyguardListener;
boolean mWaitingForUnlock;
@@ -557,6 +657,11 @@ public class WallpaperManagerService extends IWallpaperManager.Stub {
*/
int wallpaperId;
/**
* Primary colors histogram
*/
WallpaperColors primaryColors;
WallpaperConnection connection;
long lastDiedTime;
boolean wallpaperUpdating;
@@ -706,6 +811,35 @@ public class WallpaperManagerService extends IWallpaperManager.Stub {
}
}
/**
* Called by a live wallpaper if its colors have changed.
* @param primaryColors representation of wallpaper primary colors
*/
@Override
public void onWallpaperColorsChanged(WallpaperColors primaryColors) {
int which;
synchronized (mLock) {
// Do not broadcast changes on ImageWallpaper since it's handled
// internally by this class.
if (mImageWallpaper.equals(mWallpaper.wallpaperComponent)) {
return;
}
mWallpaper.primaryColors = primaryColors;
// 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(mCurrentUserId);
if (lockedWallpaper == null) {
which |= FLAG_LOCK;
}
}
if (which != 0) {
notifyWallpaperColorsChanged(mWallpaper, which);
}
}
@Override
public void attachEngine(IWallpaperEngine engine) {
synchronized (mLock) {
@@ -916,6 +1050,7 @@ public class WallpaperManagerService extends IWallpaperManager.Stub {
mMonitor.register(context, null, UserHandle.ALL, true);
getWallpaperDir(UserHandle.USER_SYSTEM).mkdirs();
loadSettingsLocked(UserHandle.USER_SYSTEM, false);
mColorsChangedListeners = new RemoteCallbackList<>();
}
private static File getWallpaperDir(int userId) {
@@ -1130,6 +1265,10 @@ public class WallpaperManagerService extends IWallpaperManager.Stub {
synchronized (mLock) {
clearWallpaperLocked(false, which, userId, null);
}
// When clearing a wallpaper, broadcast new valid colors
WallpaperData data = getWallpaperSafeLocked(mCurrentUserId, which);
notifyWallpaperColorsChanged(data, which);
}
void clearWallpaperLocked(boolean defaultFailed, int which, int userId, IRemoteCallback reply) {
@@ -1421,6 +1560,20 @@ public class WallpaperManagerService extends IWallpaperManager.Stub {
return -1;
}
@Override
public void registerWallpaperColorsCallback(IWallpaperManagerCallback cb) {
synchronized (mLock) {
mColorsChangedListeners.register(cb);
}
}
@Override
public void unregisterWallpaperColorsCallback(IWallpaperManagerCallback cb) {
synchronized (mLock) {
mColorsChangedListeners.unregister(cb);
}
}
@Override
public boolean setLockWallpaperCallback(IWallpaperManagerCallback cb) {
checkPermission(android.Manifest.permission.INTERNAL_SYSTEM_WINDOW);
@@ -1430,6 +1583,41 @@ public class WallpaperManagerService extends IWallpaperManager.Stub {
return true;
}
@Override
public WallpaperColors getWallpaperColors(int which) throws RemoteException {
if (which != FLAG_LOCK && which != FLAG_SYSTEM) {
throw new IllegalArgumentException("which should be either FLAG_LOCK or FLAG_SYSTEM");
}
WallpaperData wallpaperData = null;
boolean shouldExtract;
synchronized (mLock) {
if (which == FLAG_LOCK) {
wallpaperData = mLockWallpaperMap.get(mCurrentUserId);
}
// Try to get the system wallpaper anyway since it might
// also be the lock screen wallpaper
if (wallpaperData == null) {
wallpaperData = mWallpaperMap.get(mCurrentUserId);
}
if (wallpaperData == null) {
return null;
}
shouldExtract = wallpaperData.primaryColors == null;
}
if (shouldExtract) {
extractColors(wallpaperData);
}
synchronized (mLock) {
return wallpaperData.primaryColors;
}
}
@Override
public ParcelFileDescriptor setWallpaper(String name, String callingPackage,
Rect cropHint, boolean allowBackup, Bundle extras, int which,
@@ -1509,6 +1697,7 @@ public class WallpaperManagerService extends IWallpaperManager.Stub {
lockWP.width = sysWP.width;
lockWP.height = sysWP.height;
lockWP.allowBackup = sysWP.allowBackup;
lockWP.primaryColors = sysWP.primaryColors;
// Migrate the bitmap files outright; no need to copy
try {
@@ -1546,6 +1735,8 @@ public class WallpaperManagerService extends IWallpaperManager.Stub {
if (extras != null) {
extras.putInt(WallpaperManager.EXTRA_NEW_WALLPAPER_ID, wallpaper.wallpaperId);
}
// Nullify field to require new computation
wallpaper.primaryColors = null;
if (DEBUG) {
Slog.v(TAG, "updateWallpaperBitmapLocked() : id=" + wallpaper.wallpaperId
+ " name=" + name + " file=" + wallpaper.wallpaperFile.getName());
@@ -1577,9 +1768,13 @@ public class WallpaperManagerService extends IWallpaperManager.Stub {
false /* all */, true /* full */, "changing live wallpaper", null /* pkg */);
checkPermission(android.Manifest.permission.SET_WALLPAPER_COMPONENT);
int which = FLAG_SYSTEM;
boolean shouldNotifyColors = false;
WallpaperData wallpaper;
synchronized (mLock) {
if (DEBUG) Slog.v(TAG, "setWallpaperComponent name=" + name);
WallpaperData wallpaper = mWallpaperMap.get(userId);
wallpaper = mWallpaperMap.get(userId);
if (wallpaper == null) {
throw new IllegalStateException("Wallpaper not yet initialized for user " + userId);
}
@@ -1597,16 +1792,26 @@ public class WallpaperManagerService extends IWallpaperManager.Stub {
}
}
// New live wallpaper is also a lock wallpaper if nothing is set
if (mLockWallpaperMap.get(userId) == null) {
which |= FLAG_LOCK;
}
try {
wallpaper.imageWallpaperPending = false;
if (bindWallpaperComponentLocked(name, false, true, wallpaper, null)) {
wallpaper.wallpaperId = makeWallpaperIdLocked();
notifyCallbacksLocked(wallpaper);
shouldNotifyColors = true;
}
} finally {
Binder.restoreCallingIdentity(ident);
}
}
if (shouldNotifyColors) {
notifyWallpaperColorsChanged(wallpaper, which);
}
}
boolean bindWallpaperComponentLocked(ComponentName componentName, boolean force,
@@ -1731,6 +1936,7 @@ public class WallpaperManagerService extends IWallpaperManager.Stub {
}
wallpaper.wallpaperComponent = componentName;
wallpaper.connection = newConn;
wallpaper.primaryColors = null;
newConn.mReply = reply;
try {
if (wallpaper.userId == mCurrentUserId) {
@@ -1810,6 +2016,7 @@ public class WallpaperManagerService extends IWallpaperManager.Stub {
}
}
wallpaper.callbacks.finishBroadcast();
final Intent intent = new Intent(Intent.ACTION_WALLPAPER_CHANGED);
mContext.sendBroadcastAsUser(intent, new UserHandle(mCurrentUserId));
}
@@ -1900,6 +2107,9 @@ public class WallpaperManagerService extends IWallpaperManager.Stub {
private void writeWallpaperAttributes(XmlSerializer out, String tag, WallpaperData wallpaper)
throws IllegalArgumentException, IllegalStateException, IOException {
if (DEBUG) {
Slog.v(TAG, "writeWallpaperAttributes");
}
out.startTag(null, tag);
out.attribute(null, "id", Integer.toString(wallpaper.wallpaperId));
out.attribute(null, "width", Integer.toString(wallpaper.width));
@@ -1923,6 +2133,20 @@ public class WallpaperManagerService extends IWallpaperManager.Stub {
out.attribute(null, "paddingBottom", Integer.toString(wallpaper.padding.bottom));
}
if (wallpaper.primaryColors != null) {
int colorsCount = wallpaper.primaryColors.getColors().size();
out.attribute(null, "colorsCount", Integer.toString(colorsCount));
if (colorsCount > 0) {
for (int i = 0; i < colorsCount; i++) {
Pair<Color, Integer> wc = wallpaper.primaryColors.getColors().get(i);
out.attribute(null, "colorValue"+i, Integer.toString(wc.first.toArgb()));
out.attribute(null, "colorWeight"+i, Integer.toString(wc.second));
}
}
out.attribute(null, "supportsDarkText",
Integer.toString(wallpaper.primaryColors.supportsDarkText() ? 1 : 0));
}
out.attribute(null, "name", wallpaper.name);
if (wallpaper.wallpaperComponent != null
&& !wallpaper.wallpaperComponent.equals(mImageWallpaper)) {
@@ -2054,6 +2278,7 @@ public class WallpaperManagerService extends IWallpaperManager.Stub {
Slog.v(TAG, "mWidth:" + wallpaper.width);
Slog.v(TAG, "mHeight:" + wallpaper.height);
Slog.v(TAG, "cropRect:" + wallpaper.cropHint);
Slog.v(TAG, "primaryColors:" + wallpaper.primaryColors);
Slog.v(TAG, "mName:" + wallpaper.name);
Slog.v(TAG, "mNextWallpaperComponent:"
+ wallpaper.nextWallpaperComponent);
@@ -2152,6 +2377,18 @@ public class WallpaperManagerService extends IWallpaperManager.Stub {
wallpaper.padding.top = getAttributeInt(parser, "paddingTop", 0);
wallpaper.padding.right = getAttributeInt(parser, "paddingRight", 0);
wallpaper.padding.bottom = getAttributeInt(parser, "paddingBottom", 0);
int colorsCount = getAttributeInt(parser, "colorsCount", 0);
if (colorsCount > 0) {
List<Pair<Color, Integer>> colors = new ArrayList<>();
for (int i = 0; i < colorsCount; i++) {
colors.add(new Pair<>(
Color.valueOf(getAttributeInt(parser, "colorValue"+i, 0)),
getAttributeInt(parser, "colorWeight"+i, 0)
));
}
boolean dark = getAttributeInt(parser, "supportsDarkText", 0) == 1;
wallpaper.primaryColors = new WallpaperColors(colors, dark);
}
wallpaper.name = parser.getAttributeValue(null, "name");
wallpaper.allowBackup = "true".equals(parser.getAttributeValue(null, "backup"));
}