Fix XML serialization of WallpaperColors

WallpaperColors is serialized to disk for use the next time the device
boots. WallpaperColors wasn't serializing the quantizer results, just
the 3 "main" colors, so it was unable to identify more than a few
colors, using the AOSP algorithm.

Bug: 186203148
Test: Reboot device without patch, verify only a couple colors are
available, or none if the AOSP algorithm for selecting main colors
differed sufficiently. Verify that with patch, rebooting the device
shows the same color options in the same order as it did at runtime.
Change-Id: I881a2cfe5b7dda5b7734ce3fda7275dc5544ce0c
This commit is contained in:
James O'Leary
2021-06-21 16:53:57 -04:00
parent 0245b5cbce
commit 3a00015faa
2 changed files with 63 additions and 3 deletions

View File

@@ -129,7 +129,9 @@ 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;
import java.util.function.Consumer;
import java.util.function.Predicate;
@@ -3140,7 +3142,9 @@ public class WallpaperManagerService extends IWallpaperManager.Stub
}
}
private void writeWallpaperAttributes(TypedXmlSerializer out, String tag,
@VisibleForTesting
void writeWallpaperAttributes(TypedXmlSerializer out, String tag,
WallpaperData wallpaper)
throws IllegalArgumentException, IllegalStateException, IOException {
if (DEBUG) {
@@ -3179,6 +3183,19 @@ public class WallpaperManagerService extends IWallpaperManager.Stub
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());
}
@@ -3410,7 +3427,8 @@ public class WallpaperManagerService extends IWallpaperManager.Stub
}
}
private void parseWallpaperAttributes(TypedXmlPullParser parser, WallpaperData wallpaper,
@VisibleForTesting
void parseWallpaperAttributes(TypedXmlPullParser parser, WallpaperData wallpaper,
boolean keepDimensionHints) throws XmlPullParserException {
final int id = parser.getAttributeInt(null, "id", -1);
if (id != -1) {
@@ -3437,7 +3455,17 @@ public class WallpaperManagerService extends IWallpaperManager.Stub
wpData.mPadding.right = getAttributeInt(parser, "paddingRight", 0);
wpData.mPadding.bottom = getAttributeInt(parser, "paddingBottom", 0);
int colorsCount = getAttributeInt(parser, "colorsCount", 0);
if (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));

View File

@@ -31,6 +31,7 @@ import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import static org.junit.Assume.assumeThat;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyInt;
@@ -57,6 +58,9 @@ import android.service.wallpaper.WallpaperService;
import android.testing.TestableContext;
import android.util.Log;
import android.util.SparseArray;
import android.util.TypedXmlPullParser;
import android.util.TypedXmlSerializer;
import android.util.Xml;
import android.view.Display;
import androidx.test.filters.FlakyTest;
@@ -82,9 +86,12 @@ import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.mockito.quality.Strictness;
import org.xmlpull.v1.XmlPullParserException;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
/**
* Tests for the {@link WallpaperManagerService} class.
@@ -355,6 +362,31 @@ public class WallpaperManagerServiceTests {
verifyDisplayData();
}
@Test
public void testXmlSerializationRoundtrip() {
WallpaperData systemWallpaperData = mService.getCurrentWallpaperData(FLAG_SYSTEM, 0);
try {
TypedXmlSerializer serializer = Xml.newBinarySerializer();
serializer.setOutput(new ByteArrayOutputStream(), StandardCharsets.UTF_8.name());
serializer.startDocument(StandardCharsets.UTF_8.name(), true);
mService.writeWallpaperAttributes(serializer, "wp", systemWallpaperData);
} catch (IOException e) {
fail("exception occurred while writing system wallpaper attributes");
}
WallpaperData shouldMatchSystem = new WallpaperData(systemWallpaperData.userId,
systemWallpaperData.wallpaperFile.getParentFile(),
systemWallpaperData.wallpaperFile.getAbsolutePath(),
systemWallpaperData.cropFile.getAbsolutePath());
try {
TypedXmlPullParser parser = Xml.newBinaryPullParser();
mService.parseWallpaperAttributes(parser, shouldMatchSystem, true);
} catch (XmlPullParserException e) {
fail("exception occurred while parsing wallpaper");
}
assertEquals(systemWallpaperData.primaryColors, shouldMatchSystem.primaryColors);
}
// Verify that after continue switch user from userId 0 to lastUserId, the wallpaper data for
// non-current user must not bind to wallpaper service.
private void verifyNoConnectionBeforeLastUser(int lastUserId) {