Move xml & loading logic to a new class
Part of the WallpaperManagerService refactor Test: treehugger Test: atest CtsWallpaperTestCases Test: atest FrameworksMockingServicesTests:WallpaperManagerServiceTests Bug: 264637309 Change-Id: I27d34fed6e15e9e6bf6995f48f11f906a381330d
This commit is contained in:
@@ -30,7 +30,7 @@ import android.app.WallpaperManager.SetWallpaperFlags;
|
||||
import android.content.ComponentName;
|
||||
import android.graphics.Rect;
|
||||
import android.os.RemoteCallbackList;
|
||||
import android.util.ArrayMap;
|
||||
import android.util.SparseArray;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
@@ -115,7 +115,7 @@ class WallpaperData {
|
||||
* A map to keep track of the dimming set by different applications. The key is the calling
|
||||
* UID and the value is the dim amount.
|
||||
*/
|
||||
ArrayMap<Integer, Float> mUidToDimAmount = new ArrayMap<>();
|
||||
SparseArray<Float> mUidToDimAmount = new SparseArray<>();
|
||||
|
||||
/**
|
||||
* Whether we need to extract the wallpaper colors again to calculate the dark hints
|
||||
|
||||
@@ -0,0 +1,550 @@
|
||||
/*
|
||||
* Copyright (C) 2023 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.android.server.wallpaper;
|
||||
|
||||
import static android.app.WallpaperManager.FLAG_LOCK;
|
||||
import static android.app.WallpaperManager.FLAG_SYSTEM;
|
||||
import static android.view.Display.DEFAULT_DISPLAY;
|
||||
|
||||
import static com.android.server.wallpaper.WallpaperDisplayHelper.DisplayData;
|
||||
import static com.android.server.wallpaper.WallpaperUtils.WALLPAPER;
|
||||
import static com.android.server.wallpaper.WallpaperUtils.WALLPAPER_CROP;
|
||||
import static com.android.server.wallpaper.WallpaperUtils.WALLPAPER_INFO;
|
||||
import static com.android.server.wallpaper.WallpaperUtils.getWallpaperDir;
|
||||
import static com.android.server.wallpaper.WallpaperUtils.makeWallpaperIdLocked;
|
||||
|
||||
import android.annotation.Nullable;
|
||||
import android.app.WallpaperColors;
|
||||
import android.app.backup.WallpaperBackupHelper;
|
||||
import android.content.ComponentName;
|
||||
import android.content.Context;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.content.res.Resources;
|
||||
import android.graphics.Color;
|
||||
import android.os.FileUtils;
|
||||
import android.util.Slog;
|
||||
import android.util.SparseArray;
|
||||
import android.util.Xml;
|
||||
|
||||
import com.android.internal.R;
|
||||
import com.android.internal.annotations.VisibleForTesting;
|
||||
import com.android.internal.util.JournaledFile;
|
||||
import com.android.modules.utils.TypedXmlPullParser;
|
||||
import com.android.modules.utils.TypedXmlSerializer;
|
||||
|
||||
import libcore.io.IoUtils;
|
||||
|
||||
import org.xmlpull.v1.XmlPullParser;
|
||||
import org.xmlpull.v1.XmlPullParserException;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Helper for the wallpaper loading / saving / xml parsing
|
||||
* Only meant to be used lock held by WallpaperManagerService
|
||||
* Only meant to be instantiated once by WallpaperManagerService
|
||||
*/
|
||||
class WallpaperDataParser {
|
||||
|
||||
private static final String TAG = WallpaperDataParser.class.getSimpleName();
|
||||
private static final boolean DEBUG = false;
|
||||
private final ComponentName mImageWallpaper;
|
||||
private final WallpaperDisplayHelper mWallpaperDisplayHelper;
|
||||
private final WallpaperCropper mWallpaperCropper;
|
||||
private final Context mContext;
|
||||
|
||||
WallpaperDataParser(Context context, WallpaperDisplayHelper wallpaperDisplayHelper,
|
||||
WallpaperCropper wallpaperCropper) {
|
||||
mContext = context;
|
||||
mWallpaperDisplayHelper = wallpaperDisplayHelper;
|
||||
mWallpaperCropper = wallpaperCropper;
|
||||
mImageWallpaper = ComponentName.unflattenFromString(
|
||||
context.getResources().getString(R.string.image_wallpaper_component));
|
||||
}
|
||||
|
||||
private JournaledFile makeJournaledFile(int userId) {
|
||||
final String base = new File(getWallpaperDir(userId), WALLPAPER_INFO).getAbsolutePath();
|
||||
return new JournaledFile(new File(base), new File(base + ".tmp"));
|
||||
}
|
||||
|
||||
static class WallpaperLoadingResult {
|
||||
|
||||
private final WallpaperData mSystemWallpaperData;
|
||||
|
||||
@Nullable
|
||||
private final WallpaperData mLockWallpaperData;
|
||||
|
||||
private final boolean mSuccess;
|
||||
|
||||
private WallpaperLoadingResult(
|
||||
WallpaperData systemWallpaperData,
|
||||
WallpaperData lockWallpaperData,
|
||||
boolean success) {
|
||||
mSystemWallpaperData = systemWallpaperData;
|
||||
mLockWallpaperData = lockWallpaperData;
|
||||
mSuccess = success;
|
||||
}
|
||||
|
||||
public WallpaperData getSystemWallpaperData() {
|
||||
return mSystemWallpaperData;
|
||||
}
|
||||
|
||||
public WallpaperData getLockWallpaperData() {
|
||||
return mLockWallpaperData;
|
||||
}
|
||||
|
||||
public boolean success() {
|
||||
return mSuccess;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Load the system wallpaper (and the lock wallpaper, if it exists) from disk
|
||||
* @param userId the id of the user for which the wallpaper should be loaded
|
||||
* @param keepDimensionHints if false, parse and set the
|
||||
* {@link DisplayData} width and height for the specified userId
|
||||
* @param wallpaper the wallpaper object to reuse to do the modifications.
|
||||
* If null, a new object will be created.
|
||||
* @param lockWallpaper the lock wallpaper object to reuse to do the modifications.
|
||||
* If null, a new object will be created.
|
||||
* @return a {@link WallpaperLoadingResult} object containing the wallpaper data.
|
||||
* This object will contain the {@code wallpaper} and
|
||||
* {@code lockWallpaper} provided as parameters, if they are not null.
|
||||
*/
|
||||
public WallpaperLoadingResult loadSettingsLocked(int userId, boolean keepDimensionHints,
|
||||
WallpaperData wallpaper, WallpaperData lockWallpaper) {
|
||||
JournaledFile journal = makeJournaledFile(userId);
|
||||
FileInputStream stream = null;
|
||||
File file = journal.chooseForRead();
|
||||
|
||||
if (wallpaper == null) {
|
||||
// Do this once per boot
|
||||
migrateFromOld();
|
||||
wallpaper = new WallpaperData(userId, FLAG_SYSTEM);
|
||||
wallpaper.allowBackup = true;
|
||||
if (!wallpaper.cropExists()) {
|
||||
if (wallpaper.sourceExists()) {
|
||||
mWallpaperCropper.generateCrop(wallpaper);
|
||||
} else {
|
||||
Slog.i(TAG, "No static wallpaper imagery; defaults will be shown");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
final DisplayData wpdData = mWallpaperDisplayHelper.getDisplayDataOrCreate(DEFAULT_DISPLAY);
|
||||
boolean success = false;
|
||||
|
||||
try {
|
||||
stream = new FileInputStream(file);
|
||||
TypedXmlPullParser parser = Xml.resolvePullParser(stream);
|
||||
|
||||
int type;
|
||||
do {
|
||||
type = parser.next();
|
||||
if (type == XmlPullParser.START_TAG) {
|
||||
String tag = parser.getName();
|
||||
if ("wp".equals(tag)) {
|
||||
// Common to system + lock wallpapers
|
||||
parseWallpaperAttributes(parser, wallpaper, keepDimensionHints);
|
||||
|
||||
// A system wallpaper might also be a live wallpaper
|
||||
String comp = parser.getAttributeValue(null, "component");
|
||||
wallpaper.nextWallpaperComponent = comp != null
|
||||
? ComponentName.unflattenFromString(comp)
|
||||
: null;
|
||||
if (wallpaper.nextWallpaperComponent == null
|
||||
|| "android".equals(wallpaper.nextWallpaperComponent
|
||||
.getPackageName())) {
|
||||
wallpaper.nextWallpaperComponent = mImageWallpaper;
|
||||
}
|
||||
|
||||
if (DEBUG) {
|
||||
Slog.v(TAG, "mWidth:" + wpdData.mWidth);
|
||||
Slog.v(TAG, "mHeight:" + wpdData.mHeight);
|
||||
Slog.v(TAG, "cropRect:" + wallpaper.cropHint);
|
||||
Slog.v(TAG, "primaryColors:" + wallpaper.primaryColors);
|
||||
Slog.v(TAG, "mName:" + wallpaper.name);
|
||||
Slog.v(TAG, "mNextWallpaperComponent:"
|
||||
+ wallpaper.nextWallpaperComponent);
|
||||
}
|
||||
} else if ("kwp".equals(tag)) {
|
||||
// keyguard-specific wallpaper for this user
|
||||
|
||||
if (lockWallpaper == null) {
|
||||
lockWallpaper = new WallpaperData(userId, FLAG_LOCK);
|
||||
}
|
||||
parseWallpaperAttributes(parser, lockWallpaper, false);
|
||||
}
|
||||
}
|
||||
} while (type != XmlPullParser.END_DOCUMENT);
|
||||
success = true;
|
||||
} catch (FileNotFoundException e) {
|
||||
Slog.w(TAG, "no current wallpaper -- first boot?");
|
||||
} catch (NullPointerException e) {
|
||||
Slog.w(TAG, "failed parsing " + file + " " + e);
|
||||
} catch (NumberFormatException e) {
|
||||
Slog.w(TAG, "failed parsing " + file + " " + e);
|
||||
} catch (XmlPullParserException e) {
|
||||
Slog.w(TAG, "failed parsing " + file + " " + e);
|
||||
} catch (IOException e) {
|
||||
Slog.w(TAG, "failed parsing " + file + " " + e);
|
||||
} catch (IndexOutOfBoundsException e) {
|
||||
Slog.w(TAG, "failed parsing " + file + " " + e);
|
||||
}
|
||||
IoUtils.closeQuietly(stream);
|
||||
|
||||
if (!success) {
|
||||
wallpaper.cropHint.set(0, 0, 0, 0);
|
||||
wpdData.mPadding.set(0, 0, 0, 0);
|
||||
wallpaper.name = "";
|
||||
lockWallpaper = null;
|
||||
} else {
|
||||
if (wallpaper.wallpaperId <= 0) {
|
||||
wallpaper.wallpaperId = makeWallpaperIdLocked();
|
||||
if (DEBUG) {
|
||||
Slog.w(TAG, "Didn't set wallpaper id in loadSettingsLocked(" + userId
|
||||
+ "); now " + wallpaper.wallpaperId);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
mWallpaperDisplayHelper.ensureSaneWallpaperDisplaySize(wpdData, DEFAULT_DISPLAY);
|
||||
ensureSaneWallpaperData(wallpaper);
|
||||
if (lockWallpaper != null) {
|
||||
ensureSaneWallpaperData(lockWallpaper);
|
||||
lockWallpaper.mWhich = FLAG_LOCK;
|
||||
wallpaper.mWhich = FLAG_SYSTEM;
|
||||
} else {
|
||||
wallpaper.mWhich = FLAG_SYSTEM | FLAG_LOCK;
|
||||
}
|
||||
|
||||
return new WallpaperLoadingResult(wallpaper, lockWallpaper, success);
|
||||
}
|
||||
|
||||
private void ensureSaneWallpaperData(WallpaperData wallpaper) {
|
||||
// Only overwrite cropHint if the rectangle is invalid.
|
||||
if (wallpaper.cropHint.width() < 0
|
||||
|| wallpaper.cropHint.height() < 0) {
|
||||
wallpaper.cropHint.set(0, 0, 0, 0);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private void migrateFromOld() {
|
||||
// Pre-N, what existed is the one we're now using as the display crop
|
||||
File preNWallpaper = new File(getWallpaperDir(0), WALLPAPER_CROP);
|
||||
// In the very-long-ago, imagery lived with the settings app
|
||||
File originalWallpaper = new File(WallpaperBackupHelper.WALLPAPER_IMAGE_KEY);
|
||||
File newWallpaper = new File(getWallpaperDir(0), WALLPAPER);
|
||||
|
||||
// Migrations from earlier wallpaper image storage schemas
|
||||
if (preNWallpaper.exists()) {
|
||||
if (!newWallpaper.exists()) {
|
||||
// we've got the 'wallpaper' crop file but not the nominal source image,
|
||||
// so do the simple "just take everything" straight copy of legacy data
|
||||
if (DEBUG) {
|
||||
Slog.i(TAG, "Migrating wallpaper schema");
|
||||
}
|
||||
FileUtils.copyFile(preNWallpaper, newWallpaper);
|
||||
} // else we're in the usual modern case: both source & crop exist
|
||||
} else if (originalWallpaper.exists()) {
|
||||
// VERY old schema; make sure things exist and are in the right place
|
||||
if (DEBUG) {
|
||||
Slog.i(TAG, "Migrating antique wallpaper schema");
|
||||
}
|
||||
File oldInfo = new File(WallpaperBackupHelper.WALLPAPER_INFO_KEY);
|
||||
if (oldInfo.exists()) {
|
||||
File newInfo = new File(getWallpaperDir(0), WALLPAPER_INFO);
|
||||
oldInfo.renameTo(newInfo);
|
||||
}
|
||||
|
||||
FileUtils.copyFile(originalWallpaper, preNWallpaper);
|
||||
originalWallpaper.renameTo(newWallpaper);
|
||||
}
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
void parseWallpaperAttributes(TypedXmlPullParser parser, WallpaperData wallpaper,
|
||||
boolean keepDimensionHints) throws XmlPullParserException {
|
||||
final int id = parser.getAttributeInt(null, "id", -1);
|
||||
if (id != -1) {
|
||||
wallpaper.wallpaperId = id;
|
||||
if (id > WallpaperUtils.getCurrentWallpaperId()) {
|
||||
WallpaperUtils.setCurrentWallpaperId(id);
|
||||
}
|
||||
} else {
|
||||
wallpaper.wallpaperId = makeWallpaperIdLocked();
|
||||
}
|
||||
|
||||
final DisplayData wpData = mWallpaperDisplayHelper.getDisplayDataOrCreate(DEFAULT_DISPLAY);
|
||||
|
||||
if (!keepDimensionHints) {
|
||||
wpData.mWidth = parser.getAttributeInt(null, "width");
|
||||
wpData.mHeight = parser.getAttributeInt(null, "height");
|
||||
}
|
||||
wallpaper.cropHint.left = getAttributeInt(parser, "cropLeft", 0);
|
||||
wallpaper.cropHint.top = getAttributeInt(parser, "cropTop", 0);
|
||||
wallpaper.cropHint.right = getAttributeInt(parser, "cropRight", 0);
|
||||
wallpaper.cropHint.bottom = getAttributeInt(parser, "cropBottom", 0);
|
||||
wpData.mPadding.left = getAttributeInt(parser, "paddingLeft", 0);
|
||||
wpData.mPadding.top = getAttributeInt(parser, "paddingTop", 0);
|
||||
wpData.mPadding.right = getAttributeInt(parser, "paddingRight", 0);
|
||||
wpData.mPadding.bottom = getAttributeInt(parser, "paddingBottom", 0);
|
||||
wallpaper.mWallpaperDimAmount = getAttributeFloat(parser, "dimAmount", 0f);
|
||||
int dimAmountsCount = getAttributeInt(parser, "dimAmountsCount", 0);
|
||||
if (dimAmountsCount > 0) {
|
||||
SparseArray<Float> allDimAmounts = new SparseArray<>(dimAmountsCount);
|
||||
for (int i = 0; i < dimAmountsCount; i++) {
|
||||
int uid = getAttributeInt(parser, "dimUID" + i, 0);
|
||||
float dimValue = getAttributeFloat(parser, "dimValue" + i, 0f);
|
||||
allDimAmounts.put(uid, dimValue);
|
||||
}
|
||||
wallpaper.mUidToDimAmount = allDimAmounts;
|
||||
}
|
||||
int colorsCount = getAttributeInt(parser, "colorsCount", 0);
|
||||
int allColorsCount = getAttributeInt(parser, "allColorsCount", 0);
|
||||
if (allColorsCount > 0) {
|
||||
Map<Integer, Integer> allColors = new HashMap<>(allColorsCount);
|
||||
for (int i = 0; i < allColorsCount; i++) {
|
||||
int colorInt = getAttributeInt(parser, "allColorsValue" + i, 0);
|
||||
int population = getAttributeInt(parser, "allColorsPopulation" + i, 0);
|
||||
allColors.put(colorInt, population);
|
||||
}
|
||||
int colorHints = getAttributeInt(parser, "colorHints", 0);
|
||||
wallpaper.primaryColors = new WallpaperColors(allColors, colorHints);
|
||||
} else if (colorsCount > 0) {
|
||||
Color primary = null, secondary = null, tertiary = null;
|
||||
for (int i = 0; i < colorsCount; i++) {
|
||||
Color color = Color.valueOf(getAttributeInt(parser, "colorValue" + i, 0));
|
||||
if (i == 0) {
|
||||
primary = color;
|
||||
} else if (i == 1) {
|
||||
secondary = color;
|
||||
} else if (i == 2) {
|
||||
tertiary = color;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
int colorHints = getAttributeInt(parser, "colorHints", 0);
|
||||
wallpaper.primaryColors = new WallpaperColors(primary, secondary, tertiary, colorHints);
|
||||
}
|
||||
wallpaper.name = parser.getAttributeValue(null, "name");
|
||||
wallpaper.allowBackup = parser.getAttributeBoolean(null, "backup", false);
|
||||
}
|
||||
|
||||
private int getAttributeInt(TypedXmlPullParser parser, String name, int defValue) {
|
||||
return parser.getAttributeInt(null, name, defValue);
|
||||
}
|
||||
|
||||
private float getAttributeFloat(TypedXmlPullParser parser, String name, float defValue) {
|
||||
return parser.getAttributeFloat(null, name, defValue);
|
||||
}
|
||||
|
||||
void saveSettingsLocked(int userId, WallpaperData wallpaper, WallpaperData lockWallpaper) {
|
||||
JournaledFile journal = makeJournaledFile(userId);
|
||||
FileOutputStream fstream = null;
|
||||
try {
|
||||
fstream = new FileOutputStream(journal.chooseForWrite(), false);
|
||||
TypedXmlSerializer out = Xml.resolveSerializer(fstream);
|
||||
out.startDocument(null, true);
|
||||
|
||||
if (wallpaper != null) {
|
||||
writeWallpaperAttributes(out, "wp", wallpaper);
|
||||
}
|
||||
|
||||
if (lockWallpaper != null) {
|
||||
writeWallpaperAttributes(out, "kwp", lockWallpaper);
|
||||
}
|
||||
|
||||
out.endDocument();
|
||||
|
||||
fstream.flush();
|
||||
FileUtils.sync(fstream);
|
||||
fstream.close();
|
||||
journal.commit();
|
||||
} catch (IOException e) {
|
||||
IoUtils.closeQuietly(fstream);
|
||||
journal.rollback();
|
||||
}
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
void writeWallpaperAttributes(TypedXmlSerializer out, String tag, WallpaperData wallpaper)
|
||||
throws IllegalArgumentException, IllegalStateException, IOException {
|
||||
if (DEBUG) {
|
||||
Slog.v(TAG, "writeWallpaperAttributes id=" + wallpaper.wallpaperId);
|
||||
}
|
||||
final DisplayData wpdData = mWallpaperDisplayHelper.getDisplayDataOrCreate(DEFAULT_DISPLAY);
|
||||
out.startTag(null, tag);
|
||||
out.attributeInt(null, "id", wallpaper.wallpaperId);
|
||||
out.attributeInt(null, "width", wpdData.mWidth);
|
||||
out.attributeInt(null, "height", wpdData.mHeight);
|
||||
|
||||
out.attributeInt(null, "cropLeft", wallpaper.cropHint.left);
|
||||
out.attributeInt(null, "cropTop", wallpaper.cropHint.top);
|
||||
out.attributeInt(null, "cropRight", wallpaper.cropHint.right);
|
||||
out.attributeInt(null, "cropBottom", wallpaper.cropHint.bottom);
|
||||
|
||||
if (wpdData.mPadding.left != 0) {
|
||||
out.attributeInt(null, "paddingLeft", wpdData.mPadding.left);
|
||||
}
|
||||
if (wpdData.mPadding.top != 0) {
|
||||
out.attributeInt(null, "paddingTop", wpdData.mPadding.top);
|
||||
}
|
||||
if (wpdData.mPadding.right != 0) {
|
||||
out.attributeInt(null, "paddingRight", wpdData.mPadding.right);
|
||||
}
|
||||
if (wpdData.mPadding.bottom != 0) {
|
||||
out.attributeInt(null, "paddingBottom", wpdData.mPadding.bottom);
|
||||
}
|
||||
|
||||
out.attributeFloat(null, "dimAmount", wallpaper.mWallpaperDimAmount);
|
||||
int dimAmountsCount = wallpaper.mUidToDimAmount.size();
|
||||
out.attributeInt(null, "dimAmountsCount", dimAmountsCount);
|
||||
if (dimAmountsCount > 0) {
|
||||
int index = 0;
|
||||
for (int i = 0; i < wallpaper.mUidToDimAmount.size(); i++) {
|
||||
out.attributeInt(null, "dimUID" + index, wallpaper.mUidToDimAmount.keyAt(i));
|
||||
out.attributeFloat(null, "dimValue" + index, wallpaper.mUidToDimAmount.valueAt(i));
|
||||
index++;
|
||||
}
|
||||
}
|
||||
|
||||
if (wallpaper.primaryColors != null) {
|
||||
int colorsCount = wallpaper.primaryColors.getMainColors().size();
|
||||
out.attributeInt(null, "colorsCount", colorsCount);
|
||||
if (colorsCount > 0) {
|
||||
for (int i = 0; i < colorsCount; i++) {
|
||||
final Color wc = wallpaper.primaryColors.getMainColors().get(i);
|
||||
out.attributeInt(null, "colorValue" + i, wc.toArgb());
|
||||
}
|
||||
}
|
||||
|
||||
int allColorsCount = wallpaper.primaryColors.getAllColors().size();
|
||||
out.attributeInt(null, "allColorsCount", allColorsCount);
|
||||
if (allColorsCount > 0) {
|
||||
int index = 0;
|
||||
for (Map.Entry<Integer, Integer> entry : wallpaper.primaryColors.getAllColors()
|
||||
.entrySet()) {
|
||||
out.attributeInt(null, "allColorsValue" + index, entry.getKey());
|
||||
out.attributeInt(null, "allColorsPopulation" + index, entry.getValue());
|
||||
index++;
|
||||
}
|
||||
}
|
||||
|
||||
out.attributeInt(null, "colorHints", wallpaper.primaryColors.getColorHints());
|
||||
}
|
||||
|
||||
out.attribute(null, "name", wallpaper.name);
|
||||
if (wallpaper.wallpaperComponent != null
|
||||
&& !wallpaper.wallpaperComponent.equals(mImageWallpaper)) {
|
||||
out.attribute(null, "component",
|
||||
wallpaper.wallpaperComponent.flattenToShortString());
|
||||
}
|
||||
|
||||
if (wallpaper.allowBackup) {
|
||||
out.attributeBoolean(null, "backup", true);
|
||||
}
|
||||
|
||||
out.endTag(null, tag);
|
||||
}
|
||||
|
||||
// Restore the named resource bitmap to both source + crop files
|
||||
boolean restoreNamedResourceLocked(WallpaperData wallpaper) {
|
||||
if (wallpaper.name.length() > 4 && "res:".equals(wallpaper.name.substring(0, 4))) {
|
||||
String resName = wallpaper.name.substring(4);
|
||||
|
||||
String pkg = null;
|
||||
int colon = resName.indexOf(':');
|
||||
if (colon > 0) {
|
||||
pkg = resName.substring(0, colon);
|
||||
}
|
||||
|
||||
String ident = null;
|
||||
int slash = resName.lastIndexOf('/');
|
||||
if (slash > 0) {
|
||||
ident = resName.substring(slash + 1);
|
||||
}
|
||||
|
||||
String type = null;
|
||||
if (colon > 0 && slash > 0 && (slash - colon) > 1) {
|
||||
type = resName.substring(colon + 1, slash);
|
||||
}
|
||||
|
||||
if (pkg != null && ident != null && type != null) {
|
||||
int resId = -1;
|
||||
InputStream res = null;
|
||||
FileOutputStream fos = null;
|
||||
FileOutputStream cos = null;
|
||||
try {
|
||||
Context c = mContext.createPackageContext(pkg, Context.CONTEXT_RESTRICTED);
|
||||
Resources r = c.getResources();
|
||||
resId = r.getIdentifier(resName, null, null);
|
||||
if (resId == 0) {
|
||||
Slog.e(TAG, "couldn't resolve identifier pkg=" + pkg + " type=" + type
|
||||
+ " ident=" + ident);
|
||||
return false;
|
||||
}
|
||||
|
||||
res = r.openRawResource(resId);
|
||||
if (wallpaper.wallpaperFile.exists()) {
|
||||
wallpaper.wallpaperFile.delete();
|
||||
wallpaper.cropFile.delete();
|
||||
}
|
||||
fos = new FileOutputStream(wallpaper.wallpaperFile);
|
||||
cos = new FileOutputStream(wallpaper.cropFile);
|
||||
|
||||
byte[] buffer = new byte[32768];
|
||||
int amt;
|
||||
while ((amt = res.read(buffer)) > 0) {
|
||||
fos.write(buffer, 0, amt);
|
||||
cos.write(buffer, 0, amt);
|
||||
}
|
||||
// mWallpaperObserver will notice the close and send the change broadcast
|
||||
|
||||
Slog.v(TAG, "Restored wallpaper: " + resName);
|
||||
return true;
|
||||
} catch (PackageManager.NameNotFoundException e) {
|
||||
Slog.e(TAG, "Package name " + pkg + " not found");
|
||||
} catch (Resources.NotFoundException e) {
|
||||
Slog.e(TAG, "Resource not found: " + resId);
|
||||
} catch (IOException e) {
|
||||
Slog.e(TAG, "IOException while restoring wallpaper ", e);
|
||||
} finally {
|
||||
IoUtils.closeQuietly(res);
|
||||
if (fos != null) {
|
||||
FileUtils.sync(fos);
|
||||
}
|
||||
if (cos != null) {
|
||||
FileUtils.sync(cos);
|
||||
}
|
||||
IoUtils.closeQuietly(fos);
|
||||
IoUtils.closeQuietly(cos);
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -30,6 +30,7 @@ import android.view.DisplayInfo;
|
||||
import com.android.server.wm.WindowManagerInternal;
|
||||
|
||||
import java.util.function.Consumer;
|
||||
|
||||
/**
|
||||
* Internal class used to store all the display data relevant to the wallpapers
|
||||
*/
|
||||
|
||||
@@ -35,7 +35,6 @@ import static com.android.server.wallpaper.WallpaperDisplayHelper.DisplayData;
|
||||
import static com.android.server.wallpaper.WallpaperUtils.RECORD_FILE;
|
||||
import static com.android.server.wallpaper.WallpaperUtils.RECORD_LOCK_FILE;
|
||||
import static com.android.server.wallpaper.WallpaperUtils.WALLPAPER;
|
||||
import static com.android.server.wallpaper.WallpaperUtils.WALLPAPER_CROP;
|
||||
import static com.android.server.wallpaper.WallpaperUtils.WALLPAPER_INFO;
|
||||
import static com.android.server.wallpaper.WallpaperUtils.WALLPAPER_LOCK_ORIG;
|
||||
import static com.android.server.wallpaper.WallpaperUtils.getWallpaperDir;
|
||||
@@ -56,7 +55,6 @@ import android.app.WallpaperInfo;
|
||||
import android.app.WallpaperManager;
|
||||
import android.app.WallpaperManager.SetWallpaperFlags;
|
||||
import android.app.admin.DevicePolicyManagerInternal;
|
||||
import android.app.backup.WallpaperBackupHelper;
|
||||
import android.content.BroadcastReceiver;
|
||||
import android.content.ComponentName;
|
||||
import android.content.Context;
|
||||
@@ -70,10 +68,8 @@ import android.content.pm.PackageManagerInternal;
|
||||
import android.content.pm.ResolveInfo;
|
||||
import android.content.pm.ServiceInfo;
|
||||
import android.content.pm.UserInfo;
|
||||
import android.content.res.Resources;
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.BitmapFactory;
|
||||
import android.graphics.Color;
|
||||
import android.graphics.Rect;
|
||||
import android.graphics.RectF;
|
||||
import android.hardware.display.DisplayManager;
|
||||
@@ -101,12 +97,10 @@ import android.service.wallpaper.IWallpaperService;
|
||||
import android.service.wallpaper.WallpaperService;
|
||||
import android.system.ErrnoException;
|
||||
import android.system.Os;
|
||||
import android.util.ArrayMap;
|
||||
import android.util.EventLog;
|
||||
import android.util.Slog;
|
||||
import android.util.SparseArray;
|
||||
import android.util.SparseBooleanArray;
|
||||
import android.util.Xml;
|
||||
import android.view.Display;
|
||||
|
||||
import com.android.internal.R;
|
||||
@@ -114,9 +108,6 @@ import com.android.internal.annotations.VisibleForTesting;
|
||||
import com.android.internal.content.PackageMonitor;
|
||||
import com.android.internal.os.BackgroundThread;
|
||||
import com.android.internal.util.DumpUtils;
|
||||
import com.android.internal.util.JournaledFile;
|
||||
import com.android.modules.utils.TypedXmlPullParser;
|
||||
import com.android.modules.utils.TypedXmlSerializer;
|
||||
import com.android.server.EventLogTags;
|
||||
import com.android.server.FgThread;
|
||||
import com.android.server.LocalServices;
|
||||
@@ -125,22 +116,16 @@ import com.android.server.pm.UserManagerInternal;
|
||||
import com.android.server.utils.TimingsTraceAndSlog;
|
||||
import com.android.server.wm.WindowManagerInternal;
|
||||
|
||||
import libcore.io.IoUtils;
|
||||
|
||||
import org.xmlpull.v1.XmlPullParser;
|
||||
import org.xmlpull.v1.XmlPullParserException;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileDescriptor;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.PrintWriter;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
@@ -152,7 +137,6 @@ public class WallpaperManagerService extends IWallpaperManager.Stub
|
||||
private static final String TAG = "WallpaperManagerService";
|
||||
private static final boolean DEBUG = false;
|
||||
private static final boolean DEBUG_LIVE = true;
|
||||
private static final boolean DEBUG_CROP = true;
|
||||
|
||||
private static final @NonNull RectF LOCAL_COLOR_BOUNDS =
|
||||
new RectF(0, 0, 1, 1);
|
||||
@@ -848,6 +832,9 @@ public class WallpaperManagerService extends IWallpaperManager.Stub
|
||||
private boolean mInAmbientMode;
|
||||
private LocalColorRepository mLocalColorRepo = new LocalColorRepository();
|
||||
|
||||
@VisibleForTesting
|
||||
final WallpaperDataParser mWallpaperDataParser;
|
||||
|
||||
@VisibleForTesting
|
||||
final WallpaperDisplayHelper mWallpaperDisplayHelper;
|
||||
final WallpaperCropper mWallpaperCropper;
|
||||
@@ -1612,6 +1599,8 @@ public class WallpaperManagerService extends IWallpaperManager.Stub
|
||||
dm.registerDisplayListener(mDisplayListener, null /* handler */);
|
||||
mWallpaperDisplayHelper = new WallpaperDisplayHelper(dm, mWindowManagerInternal);
|
||||
mWallpaperCropper = new WallpaperCropper(mWallpaperDisplayHelper);
|
||||
mWallpaperDataParser = new WallpaperDataParser(
|
||||
mContext, mWallpaperDisplayHelper, mWallpaperCropper);
|
||||
mActivityManager = mContext.getSystemService(ActivityManager.class);
|
||||
mMonitor = new MyPackageMonitor();
|
||||
mColorsChangedListeners = new SparseArray<>();
|
||||
@@ -1899,7 +1888,6 @@ public class WallpaperManagerService extends IWallpaperManager.Stub
|
||||
// bound into place
|
||||
wallpaper.wallpaperComponent = wallpaper.nextWallpaperComponent;
|
||||
final WallpaperData fallback = new WallpaperData(wallpaper.userId, FLAG_LOCK);
|
||||
ensureSaneWallpaperData(fallback);
|
||||
bindWallpaperComponentLocked(mImageWallpaper, true, false, fallback, reply);
|
||||
mWaitingForUnlock = true;
|
||||
}
|
||||
@@ -2630,12 +2618,10 @@ public class WallpaperManagerService extends IWallpaperManager.Stub
|
||||
*
|
||||
* @param uidToDimAmountMap Map of UIDs to dim amounts
|
||||
*/
|
||||
private float getHighestDimAmountFromMap(ArrayMap<Integer, Float> uidToDimAmountMap) {
|
||||
private float getHighestDimAmountFromMap(SparseArray<Float> uidToDimAmountMap) {
|
||||
float maxDimAmount = 0.0f;
|
||||
for (Map.Entry<Integer, Float> entry : uidToDimAmountMap.entrySet()) {
|
||||
if (entry.getValue() > maxDimAmount) {
|
||||
maxDimAmount = entry.getValue();
|
||||
}
|
||||
for (int i = 0; i < uidToDimAmountMap.size(); i++) {
|
||||
maxDimAmount = Math.max(maxDimAmount, uidToDimAmountMap.valueAt(i));
|
||||
}
|
||||
return maxDimAmount;
|
||||
}
|
||||
@@ -3432,169 +3418,14 @@ public class WallpaperManagerService extends IWallpaperManager.Stub
|
||||
}
|
||||
}
|
||||
|
||||
private JournaledFile makeJournaledFile(int userId) {
|
||||
final String base = new File(getWallpaperDir(userId), WALLPAPER_INFO).getAbsolutePath();
|
||||
return new JournaledFile(new File(base), new File(base + ".tmp"));
|
||||
}
|
||||
|
||||
void saveSettingsLocked(int userId) {
|
||||
TimingsTraceAndSlog t = new TimingsTraceAndSlog(TAG);
|
||||
t.traceBegin("WPMS.saveSettingsLocked-" + userId);
|
||||
JournaledFile journal = makeJournaledFile(userId);
|
||||
FileOutputStream fstream = null;
|
||||
try {
|
||||
fstream = new FileOutputStream(journal.chooseForWrite(), false);
|
||||
TypedXmlSerializer out = Xml.resolveSerializer(fstream);
|
||||
out.startDocument(null, true);
|
||||
|
||||
WallpaperData wallpaper;
|
||||
|
||||
wallpaper = mWallpaperMap.get(userId);
|
||||
if (wallpaper != null) {
|
||||
writeWallpaperAttributes(out, "wp", wallpaper);
|
||||
}
|
||||
wallpaper = mLockWallpaperMap.get(userId);
|
||||
if (wallpaper != null) {
|
||||
writeWallpaperAttributes(out, "kwp", wallpaper);
|
||||
}
|
||||
|
||||
out.endDocument();
|
||||
|
||||
fstream.flush();
|
||||
FileUtils.sync(fstream);
|
||||
fstream.close();
|
||||
journal.commit();
|
||||
} catch (IOException e) {
|
||||
IoUtils.closeQuietly(fstream);
|
||||
journal.rollback();
|
||||
}
|
||||
mWallpaperDataParser.saveSettingsLocked(
|
||||
userId, mWallpaperMap.get(userId), mLockWallpaperMap.get(userId));
|
||||
t.traceEnd();
|
||||
}
|
||||
|
||||
|
||||
@VisibleForTesting
|
||||
void writeWallpaperAttributes(TypedXmlSerializer out, String tag,
|
||||
WallpaperData wallpaper)
|
||||
throws IllegalArgumentException, IllegalStateException, IOException {
|
||||
if (DEBUG) {
|
||||
Slog.v(TAG, "writeWallpaperAttributes id=" + wallpaper.wallpaperId);
|
||||
}
|
||||
final DisplayData wpdData = mWallpaperDisplayHelper.getDisplayDataOrCreate(DEFAULT_DISPLAY);
|
||||
out.startTag(null, tag);
|
||||
out.attributeInt(null, "id", wallpaper.wallpaperId);
|
||||
out.attributeInt(null, "width", wpdData.mWidth);
|
||||
out.attributeInt(null, "height", wpdData.mHeight);
|
||||
|
||||
out.attributeInt(null, "cropLeft", wallpaper.cropHint.left);
|
||||
out.attributeInt(null, "cropTop", wallpaper.cropHint.top);
|
||||
out.attributeInt(null, "cropRight", wallpaper.cropHint.right);
|
||||
out.attributeInt(null, "cropBottom", wallpaper.cropHint.bottom);
|
||||
|
||||
if (wpdData.mPadding.left != 0) {
|
||||
out.attributeInt(null, "paddingLeft", wpdData.mPadding.left);
|
||||
}
|
||||
if (wpdData.mPadding.top != 0) {
|
||||
out.attributeInt(null, "paddingTop", wpdData.mPadding.top);
|
||||
}
|
||||
if (wpdData.mPadding.right != 0) {
|
||||
out.attributeInt(null, "paddingRight", wpdData.mPadding.right);
|
||||
}
|
||||
if (wpdData.mPadding.bottom != 0) {
|
||||
out.attributeInt(null, "paddingBottom", wpdData.mPadding.bottom);
|
||||
}
|
||||
|
||||
out.attributeFloat(null, "dimAmount", wallpaper.mWallpaperDimAmount);
|
||||
int dimAmountsCount = wallpaper.mUidToDimAmount.size();
|
||||
out.attributeInt(null, "dimAmountsCount", dimAmountsCount);
|
||||
if (dimAmountsCount > 0) {
|
||||
int index = 0;
|
||||
for (Map.Entry<Integer, Float> entry : wallpaper.mUidToDimAmount.entrySet()) {
|
||||
out.attributeInt(null, "dimUID" + index, entry.getKey());
|
||||
out.attributeFloat(null, "dimValue" + index, entry.getValue());
|
||||
index++;
|
||||
}
|
||||
}
|
||||
|
||||
if (wallpaper.primaryColors != null) {
|
||||
int colorsCount = wallpaper.primaryColors.getMainColors().size();
|
||||
out.attributeInt(null, "colorsCount", colorsCount);
|
||||
if (colorsCount > 0) {
|
||||
for (int i = 0; i < colorsCount; i++) {
|
||||
final Color wc = wallpaper.primaryColors.getMainColors().get(i);
|
||||
out.attributeInt(null, "colorValue" + i, wc.toArgb());
|
||||
}
|
||||
}
|
||||
|
||||
int allColorsCount = wallpaper.primaryColors.getAllColors().size();
|
||||
out.attributeInt(null, "allColorsCount", allColorsCount);
|
||||
if (allColorsCount > 0) {
|
||||
int index = 0;
|
||||
for (Map.Entry<Integer, Integer> entry : wallpaper.primaryColors.getAllColors()
|
||||
.entrySet()) {
|
||||
out.attributeInt(null, "allColorsValue" + index, entry.getKey());
|
||||
out.attributeInt(null, "allColorsPopulation" + index, entry.getValue());
|
||||
index++;
|
||||
}
|
||||
}
|
||||
|
||||
out.attributeInt(null, "colorHints", wallpaper.primaryColors.getColorHints());
|
||||
}
|
||||
|
||||
out.attribute(null, "name", wallpaper.name);
|
||||
if (wallpaper.wallpaperComponent != null
|
||||
&& !wallpaper.wallpaperComponent.equals(mImageWallpaper)) {
|
||||
out.attribute(null, "component",
|
||||
wallpaper.wallpaperComponent.flattenToShortString());
|
||||
}
|
||||
|
||||
if (wallpaper.allowBackup) {
|
||||
out.attributeBoolean(null, "backup", true);
|
||||
}
|
||||
|
||||
out.endTag(null, tag);
|
||||
}
|
||||
|
||||
private void migrateFromOld() {
|
||||
// Pre-N, what existed is the one we're now using as the display crop
|
||||
File preNWallpaper = new File(getWallpaperDir(0), WALLPAPER_CROP);
|
||||
// In the very-long-ago, imagery lived with the settings app
|
||||
File originalWallpaper = new File(WallpaperBackupHelper.WALLPAPER_IMAGE_KEY);
|
||||
File newWallpaper = new File(getWallpaperDir(0), WALLPAPER);
|
||||
|
||||
// Migrations from earlier wallpaper image storage schemas
|
||||
if (preNWallpaper.exists()) {
|
||||
if (!newWallpaper.exists()) {
|
||||
// we've got the 'wallpaper' crop file but not the nominal source image,
|
||||
// so do the simple "just take everything" straight copy of legacy data
|
||||
if (DEBUG) {
|
||||
Slog.i(TAG, "Migrating wallpaper schema");
|
||||
}
|
||||
FileUtils.copyFile(preNWallpaper, newWallpaper);
|
||||
} // else we're in the usual modern case: both source & crop exist
|
||||
} else if (originalWallpaper.exists()) {
|
||||
// VERY old schema; make sure things exist and are in the right place
|
||||
if (DEBUG) {
|
||||
Slog.i(TAG, "Migrating antique wallpaper schema");
|
||||
}
|
||||
File oldInfo = new File(WallpaperBackupHelper.WALLPAPER_INFO_KEY);
|
||||
if (oldInfo.exists()) {
|
||||
File newInfo = new File(getWallpaperDir(0), WALLPAPER_INFO);
|
||||
oldInfo.renameTo(newInfo);
|
||||
}
|
||||
|
||||
FileUtils.copyFile(originalWallpaper, preNWallpaper);
|
||||
originalWallpaper.renameTo(newWallpaper);
|
||||
}
|
||||
}
|
||||
|
||||
private int getAttributeInt(TypedXmlPullParser parser, String name, int defValue) {
|
||||
return parser.getAttributeInt(null, name, defValue);
|
||||
}
|
||||
|
||||
private float getAttributeFloat(TypedXmlPullParser parser, String name, float defValue) {
|
||||
return parser.getAttributeFloat(null, name, defValue);
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines and returns the current wallpaper for the given user and destination, creating
|
||||
* a valid entry if it does not already exist and adding it to the appropriate wallpaper map.
|
||||
@@ -3629,14 +3460,12 @@ public class WallpaperManagerService extends IWallpaperManager.Stub
|
||||
if (which == FLAG_LOCK) {
|
||||
wallpaper = new WallpaperData(userId, FLAG_LOCK);
|
||||
mLockWallpaperMap.put(userId, wallpaper);
|
||||
ensureSaneWallpaperData(wallpaper);
|
||||
} else {
|
||||
// rationality fallback: we're in bad shape, but establishing a known
|
||||
// valid system+lock WallpaperData will keep us from dying.
|
||||
Slog.wtf(TAG, "Didn't find wallpaper in non-lock case!");
|
||||
wallpaper = new WallpaperData(userId, FLAG_SYSTEM);
|
||||
mWallpaperMap.put(userId, wallpaper);
|
||||
ensureSaneWallpaperData(wallpaper);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -3644,114 +3473,17 @@ public class WallpaperManagerService extends IWallpaperManager.Stub
|
||||
}
|
||||
|
||||
private void loadSettingsLocked(int userId, boolean keepDimensionHints) {
|
||||
JournaledFile journal = makeJournaledFile(userId);
|
||||
FileInputStream stream = null;
|
||||
File file = journal.chooseForRead();
|
||||
|
||||
WallpaperData wallpaper = mWallpaperMap.get(userId);
|
||||
if (wallpaper == null) {
|
||||
// Do this once per boot
|
||||
migrateFromOld();
|
||||
|
||||
wallpaper = new WallpaperData(userId, FLAG_SYSTEM);
|
||||
wallpaper.allowBackup = true;
|
||||
mWallpaperMap.put(userId, wallpaper);
|
||||
if (!wallpaper.cropExists()) {
|
||||
if (wallpaper.sourceExists()) {
|
||||
mWallpaperCropper.generateCrop(wallpaper);
|
||||
} else {
|
||||
Slog.i(TAG, "No static wallpaper imagery; defaults will be shown");
|
||||
}
|
||||
}
|
||||
initializeFallbackWallpaper();
|
||||
}
|
||||
boolean success = false;
|
||||
final DisplayData wpdData = mWallpaperDisplayHelper.getDisplayDataOrCreate(DEFAULT_DISPLAY);
|
||||
try {
|
||||
stream = new FileInputStream(file);
|
||||
TypedXmlPullParser parser = Xml.resolvePullParser(stream);
|
||||
|
||||
int type;
|
||||
do {
|
||||
type = parser.next();
|
||||
if (type == XmlPullParser.START_TAG) {
|
||||
String tag = parser.getName();
|
||||
if ("wp".equals(tag)) {
|
||||
// Common to system + lock wallpapers
|
||||
parseWallpaperAttributes(parser, wallpaper, keepDimensionHints);
|
||||
|
||||
// A system wallpaper might also be a live wallpaper
|
||||
String comp = parser.getAttributeValue(null, "component");
|
||||
wallpaper.nextWallpaperComponent = comp != null
|
||||
? ComponentName.unflattenFromString(comp)
|
||||
: null;
|
||||
if (wallpaper.nextWallpaperComponent == null
|
||||
|| "android".equals(wallpaper.nextWallpaperComponent
|
||||
.getPackageName())) {
|
||||
wallpaper.nextWallpaperComponent = mImageWallpaper;
|
||||
}
|
||||
|
||||
if (DEBUG) {
|
||||
Slog.v(TAG, "mWidth:" + wpdData.mWidth);
|
||||
Slog.v(TAG, "mHeight:" + wpdData.mHeight);
|
||||
Slog.v(TAG, "cropRect:" + wallpaper.cropHint);
|
||||
Slog.v(TAG, "primaryColors:" + wallpaper.primaryColors);
|
||||
Slog.v(TAG, "mName:" + wallpaper.name);
|
||||
Slog.v(TAG, "mNextWallpaperComponent:"
|
||||
+ wallpaper.nextWallpaperComponent);
|
||||
}
|
||||
} else if ("kwp".equals(tag)) {
|
||||
// keyguard-specific wallpaper for this user
|
||||
WallpaperData lockWallpaper = mLockWallpaperMap.get(userId);
|
||||
if (lockWallpaper == null) {
|
||||
lockWallpaper = new WallpaperData(userId, FLAG_LOCK);
|
||||
mLockWallpaperMap.put(userId, lockWallpaper);
|
||||
}
|
||||
parseWallpaperAttributes(parser, lockWallpaper, false);
|
||||
}
|
||||
}
|
||||
} while (type != XmlPullParser.END_DOCUMENT);
|
||||
success = true;
|
||||
} catch (FileNotFoundException e) {
|
||||
Slog.w(TAG, "no current wallpaper -- first boot?");
|
||||
} catch (NullPointerException e) {
|
||||
Slog.w(TAG, "failed parsing " + file + " " + e);
|
||||
} catch (NumberFormatException e) {
|
||||
Slog.w(TAG, "failed parsing " + file + " " + e);
|
||||
} catch (XmlPullParserException e) {
|
||||
Slog.w(TAG, "failed parsing " + file + " " + e);
|
||||
} catch (IOException e) {
|
||||
Slog.w(TAG, "failed parsing " + file + " " + e);
|
||||
} catch (IndexOutOfBoundsException e) {
|
||||
Slog.w(TAG, "failed parsing " + file + " " + e);
|
||||
}
|
||||
IoUtils.closeQuietly(stream);
|
||||
|
||||
if (!success) {
|
||||
wallpaper.cropHint.set(0, 0, 0, 0);
|
||||
wpdData.mPadding.set(0, 0, 0, 0);
|
||||
wallpaper.name = "";
|
||||
initializeFallbackWallpaper();
|
||||
WallpaperData wallpaperData = mWallpaperMap.get(userId);
|
||||
WallpaperData lockWallpaperData = mLockWallpaperMap.get(userId);
|
||||
WallpaperDataParser.WallpaperLoadingResult result = mWallpaperDataParser.loadSettingsLocked(
|
||||
userId, keepDimensionHints, wallpaperData, lockWallpaperData);
|
||||
|
||||
mWallpaperMap.put(userId, result.getSystemWallpaperData());
|
||||
if (result.success()) {
|
||||
mLockWallpaperMap.put(userId, result.getLockWallpaperData());
|
||||
} else {
|
||||
mLockWallpaperMap.remove(userId);
|
||||
} else {
|
||||
if (wallpaper.wallpaperId <= 0) {
|
||||
wallpaper.wallpaperId = makeWallpaperIdLocked();
|
||||
if (DEBUG) {
|
||||
Slog.w(TAG, "Didn't set wallpaper id in loadSettingsLocked(" + userId
|
||||
+ "); now " + wallpaper.wallpaperId);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
mWallpaperDisplayHelper.ensureSaneWallpaperDisplaySize(wpdData, DEFAULT_DISPLAY);
|
||||
ensureSaneWallpaperData(wallpaper);
|
||||
WallpaperData lockWallpaper = mLockWallpaperMap.get(userId);
|
||||
if (lockWallpaper != null) {
|
||||
ensureSaneWallpaperData(lockWallpaper);
|
||||
lockWallpaper.mWhich = FLAG_LOCK;
|
||||
wallpaper.mWhich = FLAG_SYSTEM;
|
||||
} else {
|
||||
wallpaper.mWhich = FLAG_SYSTEM | FLAG_LOCK;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3766,84 +3498,6 @@ public class WallpaperManagerService extends IWallpaperManager.Stub
|
||||
}
|
||||
}
|
||||
|
||||
private void ensureSaneWallpaperData(WallpaperData wallpaper) {
|
||||
// Only overwrite cropHint if the rectangle is invalid.
|
||||
if (wallpaper.cropHint.width() < 0
|
||||
|| wallpaper.cropHint.height() < 0) {
|
||||
wallpaper.cropHint.set(0, 0, 0, 0);
|
||||
}
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
void parseWallpaperAttributes(TypedXmlPullParser parser, WallpaperData wallpaper,
|
||||
boolean keepDimensionHints) throws XmlPullParserException {
|
||||
final int id = parser.getAttributeInt(null, "id", -1);
|
||||
if (id != -1) {
|
||||
wallpaper.wallpaperId = id;
|
||||
if (id > WallpaperUtils.getCurrentWallpaperId()) {
|
||||
WallpaperUtils.setCurrentWallpaperId(id);
|
||||
}
|
||||
} else {
|
||||
wallpaper.wallpaperId = makeWallpaperIdLocked();
|
||||
}
|
||||
|
||||
final DisplayData wpData = mWallpaperDisplayHelper.getDisplayDataOrCreate(DEFAULT_DISPLAY);
|
||||
|
||||
if (!keepDimensionHints) {
|
||||
wpData.mWidth = parser.getAttributeInt(null, "width");
|
||||
wpData.mHeight = parser.getAttributeInt(null, "height");
|
||||
}
|
||||
wallpaper.cropHint.left = getAttributeInt(parser, "cropLeft", 0);
|
||||
wallpaper.cropHint.top = getAttributeInt(parser, "cropTop", 0);
|
||||
wallpaper.cropHint.right = getAttributeInt(parser, "cropRight", 0);
|
||||
wallpaper.cropHint.bottom = getAttributeInt(parser, "cropBottom", 0);
|
||||
wpData.mPadding.left = getAttributeInt(parser, "paddingLeft", 0);
|
||||
wpData.mPadding.top = getAttributeInt(parser, "paddingTop", 0);
|
||||
wpData.mPadding.right = getAttributeInt(parser, "paddingRight", 0);
|
||||
wpData.mPadding.bottom = getAttributeInt(parser, "paddingBottom", 0);
|
||||
wallpaper.mWallpaperDimAmount = getAttributeFloat(parser, "dimAmount", 0f);
|
||||
int dimAmountsCount = getAttributeInt(parser, "dimAmountsCount", 0);
|
||||
if (dimAmountsCount > 0) {
|
||||
ArrayMap<Integer, Float> allDimAmounts = new ArrayMap<>(dimAmountsCount);
|
||||
for (int i = 0; i < dimAmountsCount; i++) {
|
||||
int uid = getAttributeInt(parser, "dimUID" + i, 0);
|
||||
float dimValue = getAttributeFloat(parser, "dimValue" + i, 0f);
|
||||
allDimAmounts.put(uid, dimValue);
|
||||
}
|
||||
wallpaper.mUidToDimAmount = allDimAmounts;
|
||||
}
|
||||
int colorsCount = getAttributeInt(parser, "colorsCount", 0);
|
||||
int allColorsCount = getAttributeInt(parser, "allColorsCount", 0);
|
||||
if (allColorsCount > 0) {
|
||||
Map<Integer, Integer> allColors = new HashMap<>(allColorsCount);
|
||||
for (int i = 0; i < allColorsCount; i++) {
|
||||
int colorInt = getAttributeInt(parser, "allColorsValue" + i, 0);
|
||||
int population = getAttributeInt(parser, "allColorsPopulation" + i, 0);
|
||||
allColors.put(colorInt, population);
|
||||
}
|
||||
int colorHints = getAttributeInt(parser, "colorHints", 0);
|
||||
wallpaper.primaryColors = new WallpaperColors(allColors, colorHints);
|
||||
} else if (colorsCount > 0) {
|
||||
Color primary = null, secondary = null, tertiary = null;
|
||||
for (int i = 0; i < colorsCount; i++) {
|
||||
Color color = Color.valueOf(getAttributeInt(parser, "colorValue" + i, 0));
|
||||
if (i == 0) {
|
||||
primary = color;
|
||||
} else if (i == 1) {
|
||||
secondary = color;
|
||||
} else if (i == 2) {
|
||||
tertiary = color;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
int colorHints = getAttributeInt(parser, "colorHints", 0);
|
||||
wallpaper.primaryColors = new WallpaperColors(primary, secondary, tertiary, colorHints);
|
||||
}
|
||||
wallpaper.name = parser.getAttributeValue(null, "name");
|
||||
wallpaper.allowBackup = parser.getAttributeBoolean(null, "backup", false);
|
||||
}
|
||||
|
||||
// Called by SystemBackupAgent after files are restored to disk.
|
||||
public void settingsRestored() {
|
||||
// Verify caller is the system
|
||||
@@ -3878,7 +3532,7 @@ public class WallpaperManagerService extends IWallpaperManager.Stub
|
||||
success = true;
|
||||
} else {
|
||||
if (DEBUG) Slog.v(TAG, "settingsRestored: attempting to restore named resource");
|
||||
success = restoreNamedResourceLocked(wallpaper);
|
||||
success = mWallpaperDataParser.restoreNamedResourceLocked(wallpaper);
|
||||
}
|
||||
if (DEBUG) Slog.v(TAG, "settingsRestored: success=" + success
|
||||
+ " id=" + wallpaper.wallpaperId);
|
||||
@@ -3901,83 +3555,6 @@ public class WallpaperManagerService extends IWallpaperManager.Stub
|
||||
}
|
||||
}
|
||||
|
||||
// Restore the named resource bitmap to both source + crop files
|
||||
private boolean restoreNamedResourceLocked(WallpaperData wallpaper) {
|
||||
if (wallpaper.name.length() > 4 && "res:".equals(wallpaper.name.substring(0, 4))) {
|
||||
String resName = wallpaper.name.substring(4);
|
||||
|
||||
String pkg = null;
|
||||
int colon = resName.indexOf(':');
|
||||
if (colon > 0) {
|
||||
pkg = resName.substring(0, colon);
|
||||
}
|
||||
|
||||
String ident = null;
|
||||
int slash = resName.lastIndexOf('/');
|
||||
if (slash > 0) {
|
||||
ident = resName.substring(slash+1);
|
||||
}
|
||||
|
||||
String type = null;
|
||||
if (colon > 0 && slash > 0 && (slash-colon) > 1) {
|
||||
type = resName.substring(colon+1, slash);
|
||||
}
|
||||
|
||||
if (pkg != null && ident != null && type != null) {
|
||||
int resId = -1;
|
||||
InputStream res = null;
|
||||
FileOutputStream fos = null;
|
||||
FileOutputStream cos = null;
|
||||
try {
|
||||
Context c = mContext.createPackageContext(pkg, Context.CONTEXT_RESTRICTED);
|
||||
Resources r = c.getResources();
|
||||
resId = r.getIdentifier(resName, null, null);
|
||||
if (resId == 0) {
|
||||
Slog.e(TAG, "couldn't resolve identifier pkg=" + pkg + " type=" + type
|
||||
+ " ident=" + ident);
|
||||
return false;
|
||||
}
|
||||
|
||||
res = r.openRawResource(resId);
|
||||
if (wallpaper.wallpaperFile.exists()) {
|
||||
wallpaper.wallpaperFile.delete();
|
||||
wallpaper.cropFile.delete();
|
||||
}
|
||||
fos = new FileOutputStream(wallpaper.wallpaperFile);
|
||||
cos = new FileOutputStream(wallpaper.cropFile);
|
||||
|
||||
byte[] buffer = new byte[32768];
|
||||
int amt;
|
||||
while ((amt=res.read(buffer)) > 0) {
|
||||
fos.write(buffer, 0, amt);
|
||||
cos.write(buffer, 0, amt);
|
||||
}
|
||||
// mWallpaperObserver will notice the close and send the change broadcast
|
||||
|
||||
Slog.v(TAG, "Restored wallpaper: " + resName);
|
||||
return true;
|
||||
} catch (NameNotFoundException e) {
|
||||
Slog.e(TAG, "Package name " + pkg + " not found");
|
||||
} catch (Resources.NotFoundException e) {
|
||||
Slog.e(TAG, "Resource not found: " + resId);
|
||||
} catch (IOException e) {
|
||||
Slog.e(TAG, "IOException while restoring wallpaper ", e);
|
||||
} finally {
|
||||
IoUtils.closeQuietly(res);
|
||||
if (fos != null) {
|
||||
FileUtils.sync(fos);
|
||||
}
|
||||
if (cos != null) {
|
||||
FileUtils.sync(cos);
|
||||
}
|
||||
IoUtils.closeQuietly(fos);
|
||||
IoUtils.closeQuietly(cos);
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override // Binder call
|
||||
public void onShellCommand(FileDescriptor in, FileDescriptor out,
|
||||
FileDescriptor err, String[] args, ShellCallback callback,
|
||||
@@ -4008,9 +3585,9 @@ public class WallpaperManagerService extends IWallpaperManager.Stub
|
||||
pw.print(" mWallpaperDimAmount="); pw.println(wallpaper.mWallpaperDimAmount);
|
||||
pw.print(" isColorExtracted="); pw.println(wallpaper.mIsColorExtractedFromDim);
|
||||
pw.println(" mUidToDimAmount:");
|
||||
for (Map.Entry<Integer, Float> entry : wallpaper.mUidToDimAmount.entrySet()) {
|
||||
pw.print(" UID="); pw.print(entry.getKey());
|
||||
pw.print(" dimAmount="); pw.println(entry.getValue());
|
||||
for (int j = 0; j < wallpaper.mUidToDimAmount.size(); j++) {
|
||||
pw.print(" UID="); pw.print(wallpaper.mUidToDimAmount.keyAt(j));
|
||||
pw.print(" dimAmount="); pw.println(wallpaper.mUidToDimAmount.valueAt(j));
|
||||
}
|
||||
if (wallpaper.connection != null) {
|
||||
WallpaperConnection conn = wallpaper.connection;
|
||||
|
||||
@@ -200,7 +200,6 @@ public class WallpaperManagerServiceTests {
|
||||
@Before
|
||||
public void setUp() {
|
||||
MockitoAnnotations.initMocks(this);
|
||||
|
||||
ExtendedMockito.doAnswer(invocation -> {
|
||||
int userId = (invocation.getArgument(0));
|
||||
return getWallpaperTestDir(userId);
|
||||
@@ -398,7 +397,8 @@ public class WallpaperManagerServiceTests {
|
||||
TypedXmlSerializer serializer = Xml.newBinarySerializer();
|
||||
serializer.setOutput(new ByteArrayOutputStream(), StandardCharsets.UTF_8.name());
|
||||
serializer.startDocument(StandardCharsets.UTF_8.name(), true);
|
||||
mService.writeWallpaperAttributes(serializer, "wp", systemWallpaperData);
|
||||
mService.mWallpaperDataParser.writeWallpaperAttributes(
|
||||
serializer, "wp", systemWallpaperData);
|
||||
} catch (IOException e) {
|
||||
fail("exception occurred while writing system wallpaper attributes");
|
||||
}
|
||||
@@ -409,7 +409,7 @@ public class WallpaperManagerServiceTests {
|
||||
systemWallpaperData.cropFile.getAbsolutePath());
|
||||
try {
|
||||
TypedXmlPullParser parser = Xml.newBinaryPullParser();
|
||||
mService.parseWallpaperAttributes(parser, shouldMatchSystem, true);
|
||||
mService.mWallpaperDataParser.parseWallpaperAttributes(parser, shouldMatchSystem, true);
|
||||
} catch (XmlPullParserException e) {
|
||||
fail("exception occurred while parsing wallpaper");
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user