Loading core/java/android/app/WallpaperManager.java +117 −25 Original line number Diff line number Diff line Loading @@ -33,6 +33,7 @@ import android.content.Context; import android.content.Intent; import android.content.pm.PackageManager; import android.content.pm.ResolveInfo; import android.content.res.Configuration; import android.content.res.Resources; import android.content.res.Resources.NotFoundException; import android.graphics.Bitmap; Loading @@ -40,6 +41,8 @@ import android.graphics.BitmapFactory; import android.graphics.BitmapRegionDecoder; import android.graphics.Canvas; import android.graphics.ColorFilter; import android.graphics.ColorSpace; import android.graphics.ImageDecoder; import android.graphics.Matrix; import android.graphics.Paint; import android.graphics.PixelFormat; Loading @@ -63,11 +66,15 @@ import android.os.SystemProperties; import android.text.TextUtils; import android.util.Log; import android.util.Pair; import android.view.Display; import android.view.WindowManagerGlobal; import com.android.internal.R; import libcore.io.IoUtils; import java.io.BufferedInputStream; import java.io.ByteArrayOutputStream; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; Loading @@ -76,7 +83,10 @@ import java.io.InputStream; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.util.ArrayList; import java.util.Arrays; import java.util.HashSet; import java.util.List; import java.util.Set; import java.util.concurrent.CountDownLatch; import java.util.concurrent.TimeUnit; Loading Loading @@ -193,7 +203,13 @@ public class WallpaperManager { */ public static final int FLAG_LOCK = 1 << 1; private static final Object sSync = new Object[0]; @UnsupportedAppUsage private static Globals sGlobals; private final Context mContext; private final boolean mWcgEnabled; private final ColorManagementProxy mCmProxy; /** * Special drawable that draws a wallpaper as fast as possible. Assumes Loading Loading @@ -388,13 +404,14 @@ public class WallpaperManager { } public Bitmap peekWallpaperBitmap(Context context, boolean returnDefault, @SetWallpaperFlags int which) { @SetWallpaperFlags int which, ColorManagementProxy cmProxy) { return peekWallpaperBitmap(context, returnDefault, which, context.getUserId(), false /* hardware */); false /* hardware */, cmProxy); } public Bitmap peekWallpaperBitmap(Context context, boolean returnDefault, @SetWallpaperFlags int which, int userId, boolean hardware) { @SetWallpaperFlags int which, int userId, boolean hardware, ColorManagementProxy cmProxy) { if (mService != null) { try { if (!mService.isWallpaperSupported(context.getOpPackageName())) { Loading @@ -412,7 +429,8 @@ public class WallpaperManager { mCachedWallpaper = null; mCachedWallpaperUserId = 0; try { mCachedWallpaper = getCurrentWallpaperLocked(context, userId, hardware); mCachedWallpaper = getCurrentWallpaperLocked( context, userId, hardware, cmProxy); mCachedWallpaperUserId = userId; } catch (OutOfMemoryError e) { Log.w(TAG, "Out of memory loading the current wallpaper: " + e); Loading Loading @@ -450,7 +468,8 @@ public class WallpaperManager { } } private Bitmap getCurrentWallpaperLocked(Context context, int userId, boolean hardware) { private Bitmap getCurrentWallpaperLocked(Context context, int userId, boolean hardware, ColorManagementProxy cmProxy) { if (mService == null) { Log.w(TAG, "WallpaperService not running"); return null; Loading @@ -458,21 +477,29 @@ public class WallpaperManager { try { Bundle params = new Bundle(); ParcelFileDescriptor fd = mService.getWallpaperWithFeature( ParcelFileDescriptor pfd = mService.getWallpaperWithFeature( context.getOpPackageName(), context.getFeatureId(), this, FLAG_SYSTEM, params, userId); if (fd != null) { try { BitmapFactory.Options options = new BitmapFactory.Options(); if (hardware) { options.inPreferredConfig = Bitmap.Config.HARDWARE; } return BitmapFactory.decodeFileDescriptor( fd.getFileDescriptor(), null, options); } catch (OutOfMemoryError e) { if (pfd != null) { try (BufferedInputStream bis = new BufferedInputStream( new ParcelFileDescriptor.AutoCloseInputStream(pfd))) { final ByteArrayOutputStream baos = new ByteArrayOutputStream(); int data; while ((data = bis.read()) != -1) { baos.write(data); } ImageDecoder.Source src = ImageDecoder.createSource(baos.toByteArray()); return ImageDecoder.decodeBitmap(src, ((decoder, info, source) -> { // Mutable and hardware config can't be set at the same time. decoder.setMutableRequired(!hardware); // Let's do color management if (cmProxy != null) { cmProxy.doColorManagement(decoder, info); } })); } catch (OutOfMemoryError | IOException e) { Log.w(TAG, "Can't decode file", e); } finally { IoUtils.closeQuietly(fd); } } } catch (RemoteException e) { Loading @@ -497,10 +524,6 @@ public class WallpaperManager { } } private static final Object sSync = new Object[0]; @UnsupportedAppUsage private static Globals sGlobals; static void initGlobals(IWallpaperManager service, Looper looper) { synchronized (sSync) { if (sGlobals == null) { Loading @@ -514,6 +537,10 @@ public class WallpaperManager { if (service != null) { initGlobals(service, context.getMainLooper()); } // Check if supports mixed color spaces composition in hardware. mWcgEnabled = context.getResources().getConfiguration().isScreenWideColorGamut() && context.getResources().getBoolean(R.bool.config_enableWcgMode); mCmProxy = new ColorManagementProxy(context); } /** Loading @@ -530,6 +557,22 @@ public class WallpaperManager { return sGlobals.mService; } /** * Indicate whether wcg (Wide Color Gamut) should be enabled. * <p> * Some devices lack of capability of mixed color spaces composition, * enable wcg on such devices might cause memory or battery concern. * <p> * Therefore, in addition to {@link Configuration#isScreenWideColorGamut()}, * we also take mixed color spaces composition (config_enableWcgMode) into account. * * @see Configuration#isScreenWideColorGamut() * @return True if wcg should be enabled for this device. */ private boolean shouldEnableWideColorGamut() { return mWcgEnabled; } /** * Retrieve the current system wallpaper; if * no wallpaper is set, the system built-in static wallpaper is returned. Loading @@ -546,7 +589,7 @@ public class WallpaperManager { * is not able to access the wallpaper. */ public Drawable getDrawable() { Bitmap bm = sGlobals.peekWallpaperBitmap(mContext, true, FLAG_SYSTEM); Bitmap bm = sGlobals.peekWallpaperBitmap(mContext, true, FLAG_SYSTEM, mCmProxy); if (bm != null) { Drawable dr = new BitmapDrawable(mContext.getResources(), bm); dr.setDither(false); Loading Loading @@ -777,7 +820,7 @@ public class WallpaperManager { * null pointer if these is none. */ public Drawable peekDrawable() { Bitmap bm = sGlobals.peekWallpaperBitmap(mContext, false, FLAG_SYSTEM); Bitmap bm = sGlobals.peekWallpaperBitmap(mContext, false, FLAG_SYSTEM, mCmProxy); if (bm != null) { Drawable dr = new BitmapDrawable(mContext.getResources(), bm); dr.setDither(false); Loading @@ -801,7 +844,7 @@ public class WallpaperManager { */ @RequiresPermission(android.Manifest.permission.READ_EXTERNAL_STORAGE) public Drawable getFastDrawable() { Bitmap bm = sGlobals.peekWallpaperBitmap(mContext, true, FLAG_SYSTEM); Bitmap bm = sGlobals.peekWallpaperBitmap(mContext, true, FLAG_SYSTEM, mCmProxy); if (bm != null) { return new FastBitmapDrawable(bm); } Loading @@ -817,13 +860,34 @@ public class WallpaperManager { */ @RequiresPermission(android.Manifest.permission.READ_EXTERNAL_STORAGE) public Drawable peekFastDrawable() { Bitmap bm = sGlobals.peekWallpaperBitmap(mContext, false, FLAG_SYSTEM); Bitmap bm = sGlobals.peekWallpaperBitmap(mContext, false, FLAG_SYSTEM, mCmProxy); if (bm != null) { return new FastBitmapDrawable(bm); } return null; } /** * Whether the wallpaper supports Wide Color Gamut or not. * @param which The wallpaper whose image file is to be retrieved. Must be a single * defined kind of wallpaper, either {@link #FLAG_SYSTEM} or {@link #FLAG_LOCK}. * @return true when supported. * * @see #FLAG_LOCK * @see #FLAG_SYSTEM * @hide */ @RequiresPermission(android.Manifest.permission.READ_EXTERNAL_STORAGE) public boolean wallpaperSupportsWcg(int which) { if (!shouldEnableWideColorGamut()) { return false; } Bitmap bitmap = sGlobals.peekWallpaperBitmap(mContext, false, which, mCmProxy); return bitmap != null && bitmap.getColorSpace() != null && bitmap.getColorSpace() != ColorSpace.get(ColorSpace.Named.SRGB) && mCmProxy.isSupportedColorSpace(bitmap.getColorSpace()); } /** * Like {@link #getDrawable()} but returns a Bitmap with default {@link Bitmap.Config}. * Loading Loading @@ -852,7 +916,8 @@ public class WallpaperManager { * @hide */ public Bitmap getBitmapAsUser(int userId, boolean hardware) { return sGlobals.peekWallpaperBitmap(mContext, true, FLAG_SYSTEM, userId, hardware); return sGlobals.peekWallpaperBitmap( mContext, true, FLAG_SYSTEM, userId, hardware, mCmProxy); } /** Loading Loading @@ -1975,6 +2040,33 @@ public class WallpaperManager { return false; } /** * A private class to help Globals#getCurrentWallpaperLocked handle color management. */ private static class ColorManagementProxy { private final Set<ColorSpace> mSupportedColorSpaces = new HashSet<>(); ColorManagementProxy(Context context) { // Get a list of supported wide gamut color spaces. Display display = context.getDisplay(); if (display != null) { mSupportedColorSpaces.addAll(Arrays.asList(display.getSupportedWideColorGamut())); } } boolean isSupportedColorSpace(ColorSpace colorSpace) { return colorSpace != null && (colorSpace == ColorSpace.get(ColorSpace.Named.SRGB) || mSupportedColorSpaces.contains(colorSpace)); } void doColorManagement(ImageDecoder decoder, ImageDecoder.ImageInfo info) { if (!isSupportedColorSpace(info.getColorSpace())) { decoder.setTargetColorSpace(ColorSpace.get(ColorSpace.Named.SRGB)); Log.w(TAG, "Not supported color space: " + info.getColorSpace()); } } } // Private completion callback for setWallpaper() synchronization private class WallpaperSetCompletion extends IWallpaperManagerCallback.Stub { final CountDownLatch mLatch; Loading core/java/android/view/Display.java +50 −0 Original line number Diff line number Diff line Loading @@ -43,7 +43,9 @@ import android.util.Log; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.util.ArrayList; import java.util.Arrays; import java.util.List; /** * Provides information about the size and density of a logical display. Loading Loading @@ -382,6 +384,23 @@ public final class Display { /** @hide */ public static final int COLOR_MODE_DISPLAY_P3 = 9; /** @hide **/ @IntDef(prefix = {"COLOR_MODE_"}, value = { COLOR_MODE_INVALID, COLOR_MODE_DEFAULT, COLOR_MODE_BT601_625, COLOR_MODE_BT601_625_UNADJUSTED, COLOR_MODE_BT601_525, COLOR_MODE_BT601_525_UNADJUSTED, COLOR_MODE_BT709, COLOR_MODE_DCI_P3, COLOR_MODE_SRGB, COLOR_MODE_ADOBE_RGB, COLOR_MODE_DISPLAY_P3 }) @Retention(RetentionPolicy.SOURCE) public @interface ColorMode {} /** * Indicates that when display is removed, all its activities will be moved to the primary * display and the topmost activity should become focused. Loading Loading @@ -959,6 +978,37 @@ public final class Display { } } /** * Gets the supported wide color gamuts of this device. * * @return Supported WCG color spaces. * @hide */ public @ColorMode ColorSpace[] getSupportedWideColorGamut() { synchronized (this) { final ColorSpace[] defaultColorSpaces = new ColorSpace[0]; updateDisplayInfoLocked(); if (!isWideColorGamut()) { return defaultColorSpaces; } final int[] colorModes = getSupportedColorModes(); final List<ColorSpace> colorSpaces = new ArrayList<>(); for (int colorMode : colorModes) { // Refer to DisplayInfo#isWideColorGamut. switch (colorMode) { case COLOR_MODE_DCI_P3: colorSpaces.add(ColorSpace.get(ColorSpace.Named.DCI_P3)); break; case COLOR_MODE_DISPLAY_P3: colorSpaces.add(ColorSpace.get(ColorSpace.Named.DISPLAY_P3)); break; } } return colorSpaces.toArray(defaultColorSpaces); } } /** * Gets the app VSYNC offset, in nanoseconds. This is a positive value indicating * the phase offset of the VSYNC events provided by Choreographer relative to the Loading core/res/res/values/config.xml +4 −0 Original line number Diff line number Diff line Loading @@ -4260,6 +4260,10 @@ <!-- Add packages here --> </string-array> <!-- Whether or not wcg (wide color gamut) should be enabled on this device, we only enabled it while the device has ability of mixed color spaces composition --> <bool name="config_enableWcgMode">false</bool> <!-- When true, enables the whitelisted app to handle bug reports from power menu short press. --> <bool name="config_bugReportHandlerEnabled">false</bool> Loading core/res/res/values/symbols.xml +3 −0 Original line number Diff line number Diff line Loading @@ -3788,6 +3788,9 @@ <java-symbol type="string" name="accessibility_freeform_caption" /> <!-- For Wide Color Gamut --> <java-symbol type="bool" name="config_enableWcgMode" /> <!-- For contacts provider. --> <java-symbol type="string" name="config_rawContactsLocalAccountName" /> <java-symbol type="string" name="config_rawContactsLocalAccountType" /> Loading packages/SystemUI/src/com/android/systemui/ImageWallpaper.java +9 −5 Original line number Diff line number Diff line Loading @@ -108,12 +108,13 @@ public class ImageWallpaper extends WallpaperService { if (mController != null) { mController.addCallback(this /* StateListener */); } mEglHelper = new EglHelper(); mRenderer = new ImageWallpaperRenderer(context, this /* SurfaceProxy */); } @Override public void onCreate(SurfaceHolder surfaceHolder) { mEglHelper = new EglHelper(); // Deferred init renderer because we need to get wallpaper by display context. mRenderer = new ImageWallpaperRenderer(getDisplayContext(), this /* SurfaceProxy */); setFixedSizeAllowed(true); setOffsetNotificationsEnabled(true); updateSurfaceSize(); Loading Loading @@ -177,14 +178,13 @@ public class ImageWallpaper extends WallpaperService { mRenderer = null; mEglHelper.finish(); mEglHelper = null; getSurfaceHolder().getSurface().hwuiDestroy(); }); } @Override public void onSurfaceCreated(SurfaceHolder holder) { mWorker.getThreadHandler().post(() -> { mEglHelper.init(holder); mEglHelper.init(holder, needSupportWideColorGamut()); mRenderer.onSurfaceCreated(); }); } Loading Loading @@ -257,7 +257,7 @@ public class ImageWallpaper extends WallpaperService { // Check if we need to recreate egl surface. if (mEglHelper.hasEglContext() && !mEglHelper.hasEglSurface()) { if (!mEglHelper.createEglSurface(getSurfaceHolder())) { if (!mEglHelper.createEglSurface(getSurfaceHolder(), needSupportWideColorGamut())) { Log.w(TAG, "recreate egl surface failed!"); } } Loading Loading @@ -340,6 +340,10 @@ public class ImageWallpaper extends WallpaperService { && mController.getState() == StatusBarState.KEYGUARD; } private boolean needSupportWideColorGamut() { return mRenderer.isWcgContent(); } @Override protected void dump(String prefix, FileDescriptor fd, PrintWriter out, String[] args) { super.dump(prefix, fd, out, args); Loading Loading
core/java/android/app/WallpaperManager.java +117 −25 Original line number Diff line number Diff line Loading @@ -33,6 +33,7 @@ import android.content.Context; import android.content.Intent; import android.content.pm.PackageManager; import android.content.pm.ResolveInfo; import android.content.res.Configuration; import android.content.res.Resources; import android.content.res.Resources.NotFoundException; import android.graphics.Bitmap; Loading @@ -40,6 +41,8 @@ import android.graphics.BitmapFactory; import android.graphics.BitmapRegionDecoder; import android.graphics.Canvas; import android.graphics.ColorFilter; import android.graphics.ColorSpace; import android.graphics.ImageDecoder; import android.graphics.Matrix; import android.graphics.Paint; import android.graphics.PixelFormat; Loading @@ -63,11 +66,15 @@ import android.os.SystemProperties; import android.text.TextUtils; import android.util.Log; import android.util.Pair; import android.view.Display; import android.view.WindowManagerGlobal; import com.android.internal.R; import libcore.io.IoUtils; import java.io.BufferedInputStream; import java.io.ByteArrayOutputStream; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; Loading @@ -76,7 +83,10 @@ import java.io.InputStream; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.util.ArrayList; import java.util.Arrays; import java.util.HashSet; import java.util.List; import java.util.Set; import java.util.concurrent.CountDownLatch; import java.util.concurrent.TimeUnit; Loading Loading @@ -193,7 +203,13 @@ public class WallpaperManager { */ public static final int FLAG_LOCK = 1 << 1; private static final Object sSync = new Object[0]; @UnsupportedAppUsage private static Globals sGlobals; private final Context mContext; private final boolean mWcgEnabled; private final ColorManagementProxy mCmProxy; /** * Special drawable that draws a wallpaper as fast as possible. Assumes Loading Loading @@ -388,13 +404,14 @@ public class WallpaperManager { } public Bitmap peekWallpaperBitmap(Context context, boolean returnDefault, @SetWallpaperFlags int which) { @SetWallpaperFlags int which, ColorManagementProxy cmProxy) { return peekWallpaperBitmap(context, returnDefault, which, context.getUserId(), false /* hardware */); false /* hardware */, cmProxy); } public Bitmap peekWallpaperBitmap(Context context, boolean returnDefault, @SetWallpaperFlags int which, int userId, boolean hardware) { @SetWallpaperFlags int which, int userId, boolean hardware, ColorManagementProxy cmProxy) { if (mService != null) { try { if (!mService.isWallpaperSupported(context.getOpPackageName())) { Loading @@ -412,7 +429,8 @@ public class WallpaperManager { mCachedWallpaper = null; mCachedWallpaperUserId = 0; try { mCachedWallpaper = getCurrentWallpaperLocked(context, userId, hardware); mCachedWallpaper = getCurrentWallpaperLocked( context, userId, hardware, cmProxy); mCachedWallpaperUserId = userId; } catch (OutOfMemoryError e) { Log.w(TAG, "Out of memory loading the current wallpaper: " + e); Loading Loading @@ -450,7 +468,8 @@ public class WallpaperManager { } } private Bitmap getCurrentWallpaperLocked(Context context, int userId, boolean hardware) { private Bitmap getCurrentWallpaperLocked(Context context, int userId, boolean hardware, ColorManagementProxy cmProxy) { if (mService == null) { Log.w(TAG, "WallpaperService not running"); return null; Loading @@ -458,21 +477,29 @@ public class WallpaperManager { try { Bundle params = new Bundle(); ParcelFileDescriptor fd = mService.getWallpaperWithFeature( ParcelFileDescriptor pfd = mService.getWallpaperWithFeature( context.getOpPackageName(), context.getFeatureId(), this, FLAG_SYSTEM, params, userId); if (fd != null) { try { BitmapFactory.Options options = new BitmapFactory.Options(); if (hardware) { options.inPreferredConfig = Bitmap.Config.HARDWARE; } return BitmapFactory.decodeFileDescriptor( fd.getFileDescriptor(), null, options); } catch (OutOfMemoryError e) { if (pfd != null) { try (BufferedInputStream bis = new BufferedInputStream( new ParcelFileDescriptor.AutoCloseInputStream(pfd))) { final ByteArrayOutputStream baos = new ByteArrayOutputStream(); int data; while ((data = bis.read()) != -1) { baos.write(data); } ImageDecoder.Source src = ImageDecoder.createSource(baos.toByteArray()); return ImageDecoder.decodeBitmap(src, ((decoder, info, source) -> { // Mutable and hardware config can't be set at the same time. decoder.setMutableRequired(!hardware); // Let's do color management if (cmProxy != null) { cmProxy.doColorManagement(decoder, info); } })); } catch (OutOfMemoryError | IOException e) { Log.w(TAG, "Can't decode file", e); } finally { IoUtils.closeQuietly(fd); } } } catch (RemoteException e) { Loading @@ -497,10 +524,6 @@ public class WallpaperManager { } } private static final Object sSync = new Object[0]; @UnsupportedAppUsage private static Globals sGlobals; static void initGlobals(IWallpaperManager service, Looper looper) { synchronized (sSync) { if (sGlobals == null) { Loading @@ -514,6 +537,10 @@ public class WallpaperManager { if (service != null) { initGlobals(service, context.getMainLooper()); } // Check if supports mixed color spaces composition in hardware. mWcgEnabled = context.getResources().getConfiguration().isScreenWideColorGamut() && context.getResources().getBoolean(R.bool.config_enableWcgMode); mCmProxy = new ColorManagementProxy(context); } /** Loading @@ -530,6 +557,22 @@ public class WallpaperManager { return sGlobals.mService; } /** * Indicate whether wcg (Wide Color Gamut) should be enabled. * <p> * Some devices lack of capability of mixed color spaces composition, * enable wcg on such devices might cause memory or battery concern. * <p> * Therefore, in addition to {@link Configuration#isScreenWideColorGamut()}, * we also take mixed color spaces composition (config_enableWcgMode) into account. * * @see Configuration#isScreenWideColorGamut() * @return True if wcg should be enabled for this device. */ private boolean shouldEnableWideColorGamut() { return mWcgEnabled; } /** * Retrieve the current system wallpaper; if * no wallpaper is set, the system built-in static wallpaper is returned. Loading @@ -546,7 +589,7 @@ public class WallpaperManager { * is not able to access the wallpaper. */ public Drawable getDrawable() { Bitmap bm = sGlobals.peekWallpaperBitmap(mContext, true, FLAG_SYSTEM); Bitmap bm = sGlobals.peekWallpaperBitmap(mContext, true, FLAG_SYSTEM, mCmProxy); if (bm != null) { Drawable dr = new BitmapDrawable(mContext.getResources(), bm); dr.setDither(false); Loading Loading @@ -777,7 +820,7 @@ public class WallpaperManager { * null pointer if these is none. */ public Drawable peekDrawable() { Bitmap bm = sGlobals.peekWallpaperBitmap(mContext, false, FLAG_SYSTEM); Bitmap bm = sGlobals.peekWallpaperBitmap(mContext, false, FLAG_SYSTEM, mCmProxy); if (bm != null) { Drawable dr = new BitmapDrawable(mContext.getResources(), bm); dr.setDither(false); Loading @@ -801,7 +844,7 @@ public class WallpaperManager { */ @RequiresPermission(android.Manifest.permission.READ_EXTERNAL_STORAGE) public Drawable getFastDrawable() { Bitmap bm = sGlobals.peekWallpaperBitmap(mContext, true, FLAG_SYSTEM); Bitmap bm = sGlobals.peekWallpaperBitmap(mContext, true, FLAG_SYSTEM, mCmProxy); if (bm != null) { return new FastBitmapDrawable(bm); } Loading @@ -817,13 +860,34 @@ public class WallpaperManager { */ @RequiresPermission(android.Manifest.permission.READ_EXTERNAL_STORAGE) public Drawable peekFastDrawable() { Bitmap bm = sGlobals.peekWallpaperBitmap(mContext, false, FLAG_SYSTEM); Bitmap bm = sGlobals.peekWallpaperBitmap(mContext, false, FLAG_SYSTEM, mCmProxy); if (bm != null) { return new FastBitmapDrawable(bm); } return null; } /** * Whether the wallpaper supports Wide Color Gamut or not. * @param which The wallpaper whose image file is to be retrieved. Must be a single * defined kind of wallpaper, either {@link #FLAG_SYSTEM} or {@link #FLAG_LOCK}. * @return true when supported. * * @see #FLAG_LOCK * @see #FLAG_SYSTEM * @hide */ @RequiresPermission(android.Manifest.permission.READ_EXTERNAL_STORAGE) public boolean wallpaperSupportsWcg(int which) { if (!shouldEnableWideColorGamut()) { return false; } Bitmap bitmap = sGlobals.peekWallpaperBitmap(mContext, false, which, mCmProxy); return bitmap != null && bitmap.getColorSpace() != null && bitmap.getColorSpace() != ColorSpace.get(ColorSpace.Named.SRGB) && mCmProxy.isSupportedColorSpace(bitmap.getColorSpace()); } /** * Like {@link #getDrawable()} but returns a Bitmap with default {@link Bitmap.Config}. * Loading Loading @@ -852,7 +916,8 @@ public class WallpaperManager { * @hide */ public Bitmap getBitmapAsUser(int userId, boolean hardware) { return sGlobals.peekWallpaperBitmap(mContext, true, FLAG_SYSTEM, userId, hardware); return sGlobals.peekWallpaperBitmap( mContext, true, FLAG_SYSTEM, userId, hardware, mCmProxy); } /** Loading Loading @@ -1975,6 +2040,33 @@ public class WallpaperManager { return false; } /** * A private class to help Globals#getCurrentWallpaperLocked handle color management. */ private static class ColorManagementProxy { private final Set<ColorSpace> mSupportedColorSpaces = new HashSet<>(); ColorManagementProxy(Context context) { // Get a list of supported wide gamut color spaces. Display display = context.getDisplay(); if (display != null) { mSupportedColorSpaces.addAll(Arrays.asList(display.getSupportedWideColorGamut())); } } boolean isSupportedColorSpace(ColorSpace colorSpace) { return colorSpace != null && (colorSpace == ColorSpace.get(ColorSpace.Named.SRGB) || mSupportedColorSpaces.contains(colorSpace)); } void doColorManagement(ImageDecoder decoder, ImageDecoder.ImageInfo info) { if (!isSupportedColorSpace(info.getColorSpace())) { decoder.setTargetColorSpace(ColorSpace.get(ColorSpace.Named.SRGB)); Log.w(TAG, "Not supported color space: " + info.getColorSpace()); } } } // Private completion callback for setWallpaper() synchronization private class WallpaperSetCompletion extends IWallpaperManagerCallback.Stub { final CountDownLatch mLatch; Loading
core/java/android/view/Display.java +50 −0 Original line number Diff line number Diff line Loading @@ -43,7 +43,9 @@ import android.util.Log; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.util.ArrayList; import java.util.Arrays; import java.util.List; /** * Provides information about the size and density of a logical display. Loading Loading @@ -382,6 +384,23 @@ public final class Display { /** @hide */ public static final int COLOR_MODE_DISPLAY_P3 = 9; /** @hide **/ @IntDef(prefix = {"COLOR_MODE_"}, value = { COLOR_MODE_INVALID, COLOR_MODE_DEFAULT, COLOR_MODE_BT601_625, COLOR_MODE_BT601_625_UNADJUSTED, COLOR_MODE_BT601_525, COLOR_MODE_BT601_525_UNADJUSTED, COLOR_MODE_BT709, COLOR_MODE_DCI_P3, COLOR_MODE_SRGB, COLOR_MODE_ADOBE_RGB, COLOR_MODE_DISPLAY_P3 }) @Retention(RetentionPolicy.SOURCE) public @interface ColorMode {} /** * Indicates that when display is removed, all its activities will be moved to the primary * display and the topmost activity should become focused. Loading Loading @@ -959,6 +978,37 @@ public final class Display { } } /** * Gets the supported wide color gamuts of this device. * * @return Supported WCG color spaces. * @hide */ public @ColorMode ColorSpace[] getSupportedWideColorGamut() { synchronized (this) { final ColorSpace[] defaultColorSpaces = new ColorSpace[0]; updateDisplayInfoLocked(); if (!isWideColorGamut()) { return defaultColorSpaces; } final int[] colorModes = getSupportedColorModes(); final List<ColorSpace> colorSpaces = new ArrayList<>(); for (int colorMode : colorModes) { // Refer to DisplayInfo#isWideColorGamut. switch (colorMode) { case COLOR_MODE_DCI_P3: colorSpaces.add(ColorSpace.get(ColorSpace.Named.DCI_P3)); break; case COLOR_MODE_DISPLAY_P3: colorSpaces.add(ColorSpace.get(ColorSpace.Named.DISPLAY_P3)); break; } } return colorSpaces.toArray(defaultColorSpaces); } } /** * Gets the app VSYNC offset, in nanoseconds. This is a positive value indicating * the phase offset of the VSYNC events provided by Choreographer relative to the Loading
core/res/res/values/config.xml +4 −0 Original line number Diff line number Diff line Loading @@ -4260,6 +4260,10 @@ <!-- Add packages here --> </string-array> <!-- Whether or not wcg (wide color gamut) should be enabled on this device, we only enabled it while the device has ability of mixed color spaces composition --> <bool name="config_enableWcgMode">false</bool> <!-- When true, enables the whitelisted app to handle bug reports from power menu short press. --> <bool name="config_bugReportHandlerEnabled">false</bool> Loading
core/res/res/values/symbols.xml +3 −0 Original line number Diff line number Diff line Loading @@ -3788,6 +3788,9 @@ <java-symbol type="string" name="accessibility_freeform_caption" /> <!-- For Wide Color Gamut --> <java-symbol type="bool" name="config_enableWcgMode" /> <!-- For contacts provider. --> <java-symbol type="string" name="config_rawContactsLocalAccountName" /> <java-symbol type="string" name="config_rawContactsLocalAccountType" /> Loading
packages/SystemUI/src/com/android/systemui/ImageWallpaper.java +9 −5 Original line number Diff line number Diff line Loading @@ -108,12 +108,13 @@ public class ImageWallpaper extends WallpaperService { if (mController != null) { mController.addCallback(this /* StateListener */); } mEglHelper = new EglHelper(); mRenderer = new ImageWallpaperRenderer(context, this /* SurfaceProxy */); } @Override public void onCreate(SurfaceHolder surfaceHolder) { mEglHelper = new EglHelper(); // Deferred init renderer because we need to get wallpaper by display context. mRenderer = new ImageWallpaperRenderer(getDisplayContext(), this /* SurfaceProxy */); setFixedSizeAllowed(true); setOffsetNotificationsEnabled(true); updateSurfaceSize(); Loading Loading @@ -177,14 +178,13 @@ public class ImageWallpaper extends WallpaperService { mRenderer = null; mEglHelper.finish(); mEglHelper = null; getSurfaceHolder().getSurface().hwuiDestroy(); }); } @Override public void onSurfaceCreated(SurfaceHolder holder) { mWorker.getThreadHandler().post(() -> { mEglHelper.init(holder); mEglHelper.init(holder, needSupportWideColorGamut()); mRenderer.onSurfaceCreated(); }); } Loading Loading @@ -257,7 +257,7 @@ public class ImageWallpaper extends WallpaperService { // Check if we need to recreate egl surface. if (mEglHelper.hasEglContext() && !mEglHelper.hasEglSurface()) { if (!mEglHelper.createEglSurface(getSurfaceHolder())) { if (!mEglHelper.createEglSurface(getSurfaceHolder(), needSupportWideColorGamut())) { Log.w(TAG, "recreate egl surface failed!"); } } Loading Loading @@ -340,6 +340,10 @@ public class ImageWallpaper extends WallpaperService { && mController.getState() == StatusBarState.KEYGUARD; } private boolean needSupportWideColorGamut() { return mRenderer.isWcgContent(); } @Override protected void dump(String prefix, FileDescriptor fd, PrintWriter out, String[] args) { super.dump(prefix, fd, out, args); Loading