diff options
| author | 2024-03-05 04:38:09 +0000 | |
|---|---|---|
| committer | 2024-03-05 23:00:32 +0000 | |
| commit | 766426be105d99f85c79c15cf372db3e1f18163d (patch) | |
| tree | 489d8e9c0ae0a8949762633c228d6cc9b21b90f1 | |
| parent | 7440b1ee598ff6fd32dbfcae28b2fb7b1940ed7f (diff) | |
Add device dimension data to wallpaper backup flow
This CL adds device dimension data for the src device that the backup was performed on (in the backup flow). It also adds logging to indicate when the backup
occuring from a small to a large device.
unit test results: http://ab/I34300010251184653
Flag: NONE
Bug: 324257610
Test: atest WallpaperBackupAgentTest --request-upload-result
Change-Id: Ifa14a8fc2e7f2955157cb41eb128ebe27deabfc2
| -rw-r--r-- | packages/WallpaperBackup/src/com/android/wallpaperbackup/WallpaperBackupAgent.java | 232 | ||||
| -rw-r--r-- | packages/WallpaperBackup/test/src/com/android/wallpaperbackup/WallpaperBackupAgentTest.java | 21 |
2 files changed, 253 insertions, 0 deletions
diff --git a/packages/WallpaperBackup/src/com/android/wallpaperbackup/WallpaperBackupAgent.java b/packages/WallpaperBackup/src/com/android/wallpaperbackup/WallpaperBackupAgent.java index f31eb44f23f5..23e269a67283 100644 --- a/packages/WallpaperBackup/src/com/android/wallpaperbackup/WallpaperBackupAgent.java +++ b/packages/WallpaperBackup/src/com/android/wallpaperbackup/WallpaperBackupAgent.java @@ -39,7 +39,9 @@ import android.content.Context; import android.content.SharedPreferences; import android.content.pm.IPackageManager; import android.content.pm.PackageInfo; +import android.graphics.Point; import android.graphics.Rect; +import android.hardware.display.DisplayManager; import android.os.FileUtils; import android.os.ParcelFileDescriptor; import android.os.RemoteException; @@ -49,16 +51,22 @@ import android.util.Pair; import android.util.Slog; import android.util.SparseArray; import android.util.Xml; +import android.view.Display; +import android.view.DisplayInfo; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.content.PackageMonitor; +import com.android.modules.utils.TypedXmlPullParser; +import com.android.modules.utils.TypedXmlSerializer; import org.xmlpull.v1.XmlPullParser; +import org.xmlpull.v1.XmlPullParserException; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; +import java.util.ArrayList; import java.util.List; /** @@ -102,6 +110,9 @@ public class WallpaperBackupAgent extends BackupAgent { @VisibleForTesting static final String WALLPAPER_INFO_STAGE = "wallpaper-info-stage"; + @VisibleForTesting + static final String WALLPAPER_BACKUP_DEVICE_INFO_STAGE = "wallpaper-backup-device-info-stage"; + static final String EMPTY_SENTINEL = "empty"; static final String QUOTA_SENTINEL = "quota"; @@ -110,6 +121,11 @@ public class WallpaperBackupAgent extends BackupAgent { static final String SYSTEM_GENERATION = "system_gen"; static final String LOCK_GENERATION = "lock_gen"; + /** + * An approximate area threshold to compare device dimension similarity + */ + static final int AREA_THRESHOLD = 50; // TODO (b/327637867): determine appropriate threshold + // If this file exists, it means we exceeded our quota last time private File mQuotaFile; private boolean mQuotaExceeded; @@ -121,6 +137,8 @@ public class WallpaperBackupAgent extends BackupAgent { private boolean mSystemHasLiveComponent; private boolean mLockHasLiveComponent; + private DisplayManager mDisplayManager; + @Override public void onCreate() { if (DEBUG) { @@ -137,6 +155,8 @@ public class WallpaperBackupAgent extends BackupAgent { mBackupManager = new BackupManager(getBaseContext()); mEventLogger = new WallpaperEventLogger(mBackupManager, /* wallpaperAgent */ this); + + mDisplayManager = getSystemService(DisplayManager.class); } @Override @@ -175,9 +195,11 @@ public class WallpaperBackupAgent extends BackupAgent { mSystemHasLiveComponent = mWallpaperManager.getWallpaperInfo(FLAG_SYSTEM) != null; mLockHasLiveComponent = mWallpaperManager.getWallpaperInfo(FLAG_LOCK) != null; + // performing backup of each file based on order of importance backupWallpaperInfoFile(/* sysOrLockChanged= */ sysChanged || lockChanged, data); backupSystemWallpaperFile(sharedPrefs, sysChanged, sysGeneration, data); backupLockWallpaperFileIfItExists(sharedPrefs, lockChanged, lockGeneration, data); + backupDeviceInfoFile(data); } catch (Exception e) { Slog.e(TAG, "Unable to back up wallpaper", e); mEventLogger.onBackupException(e); @@ -191,6 +213,54 @@ public class WallpaperBackupAgent extends BackupAgent { } } + /** + * This method backs up the device dimension information. The device data will always get + * overwritten when triggering a backup + */ + private void backupDeviceInfoFile(FullBackupDataOutput data) + throws IOException { + final File deviceInfoStage = new File(getFilesDir(), WALLPAPER_BACKUP_DEVICE_INFO_STAGE); + + // save the dimensions of the device with xml formatting + Point dimensions = getScreenDimensions(); + Display smallerDisplay = getSmallerDisplayIfExists(); + Point secondaryDimensions = smallerDisplay != null ? getRealSize(smallerDisplay) : + new Point(0, 0); + + deviceInfoStage.createNewFile(); + FileOutputStream fstream = new FileOutputStream(deviceInfoStage, false); + TypedXmlSerializer out = Xml.resolveSerializer(fstream); + out.startDocument(null, true); + out.startTag(null, "dimensions"); + + out.startTag(null, "width"); + out.text(String.valueOf(dimensions.x)); + out.endTag(null, "width"); + + out.startTag(null, "height"); + out.text(String.valueOf(dimensions.y)); + out.endTag(null, "height"); + + if (smallerDisplay != null) { + out.startTag(null, "secondarywidth"); + out.text(String.valueOf(secondaryDimensions.x)); + out.endTag(null, "secondarywidth"); + + out.startTag(null, "secondaryheight"); + out.text(String.valueOf(secondaryDimensions.y)); + out.endTag(null, "secondaryheight"); + } + + out.endTag(null, "dimensions"); + out.endDocument(); + fstream.flush(); + FileUtils.sync(fstream); + fstream.close(); + + if (DEBUG) Slog.v(TAG, "Storing device dimension data"); + backupFile(deviceInfoStage, data); + } + private void backupWallpaperInfoFile(boolean sysOrLockChanged, FullBackupDataOutput data) throws IOException { final ParcelFileDescriptor wallpaperInfoFd = mWallpaperManager.getWallpaperInfoFile(); @@ -364,9 +434,22 @@ public class WallpaperBackupAgent extends BackupAgent { final File infoStage = new File(filesDir, WALLPAPER_INFO_STAGE); final File imageStage = new File(filesDir, SYSTEM_WALLPAPER_STAGE); final File lockImageStage = new File(filesDir, LOCK_WALLPAPER_STAGE); + final File deviceDimensionsStage = new File(filesDir, WALLPAPER_BACKUP_DEVICE_INFO_STAGE); boolean lockImageStageExists = lockImageStage.exists(); try { + // Parse the device dimensions of the source device and compare with target to + // to identify whether we need to skip the remainder of the restore process + Pair<Point, Point> sourceDeviceDimensions = parseDeviceDimensions( + deviceDimensionsStage); + + Point targetDeviceDimensions = getScreenDimensions(); + if (sourceDeviceDimensions != null && targetDeviceDimensions != null + && isSourceDeviceSignificantlySmallerThanTarget(sourceDeviceDimensions.first, + targetDeviceDimensions)) { + Slog.d(TAG, "The source device is significantly smaller than target"); + } + // First parse the live component name so that we know for logging if we care about // logging errors with the image restore. ComponentName wpService = parseWallpaperComponent(infoStage, "wp"); @@ -400,6 +483,7 @@ public class WallpaperBackupAgent extends BackupAgent { infoStage.delete(); imageStage.delete(); lockImageStage.delete(); + deviceDimensionsStage.delete(); SharedPreferences prefs = getSharedPreferences(PREFS_NAME, Context.MODE_PRIVATE); prefs.edit() @@ -409,6 +493,66 @@ public class WallpaperBackupAgent extends BackupAgent { } } + /** + * This method parses the given file for the backed up device dimensions + * + * @param deviceDimensions the file which holds the device dimensions + * @return the backed up device dimensions + */ + private Pair<Point, Point> parseDeviceDimensions(File deviceDimensions) { + int width = 0, height = 0, secondaryHeight = 0, secondaryWidth = 0; + try { + TypedXmlPullParser parser = Xml.resolvePullParser( + new FileInputStream(deviceDimensions)); + + while (parser.next() != XmlPullParser.END_TAG) { + if (parser.getEventType() != XmlPullParser.START_TAG) { + continue; + } + + String name = parser.getName(); + + switch (name) { + case "width": + String widthText = readText(parser); + width = Integer.valueOf(widthText); + break; + + case "height": + String textHeight = readText(parser); + height = Integer.valueOf(textHeight); + break; + + case "secondarywidth": + String secondaryWidthText = readText(parser); + secondaryWidth = Integer.valueOf(secondaryWidthText); + break; + + case "secondaryheight": + String secondaryHeightText = readText(parser); + secondaryHeight = Integer.valueOf(secondaryHeightText); + break; + default: + break; + } + } + return new Pair<>(new Point(width, height), new Point(secondaryWidth, secondaryHeight)); + + } catch (Exception e) { + return null; + } + } + + private static String readText(TypedXmlPullParser parser) + throws IOException, XmlPullParserException { + String result = ""; + if (parser.next() == XmlPullParser.TEXT) { + result = parser.getText(); + parser.nextTag(); + } + return result; + } + @VisibleForTesting void updateWallpaperComponent(ComponentName wpService, int which) throws IOException { @@ -691,6 +835,94 @@ public class WallpaperBackupAgent extends BackupAgent { }; } + /** + * This method retrieves the dimensions of the largest display of the device + * + * @return a @{Point} object that contains the dimensions of the largest display on the device + */ + private Point getScreenDimensions() { + Point largetDimensions = null; + int maxArea = 0; + + for (Display display : getInternalDisplays()) { + Point displaySize = getRealSize(display); + + int width = displaySize.x; + int height = displaySize.y; + int area = width * height; + + if (area > maxArea) { + maxArea = area; + largetDimensions = displaySize; + } + } + + return largetDimensions; + } + + private Point getRealSize(Display display) { + DisplayInfo displayInfo = new DisplayInfo(); + display.getDisplayInfo(displayInfo); + return new Point(displayInfo.logicalWidth, displayInfo.logicalHeight); + } + + /** + * This method returns the smaller display on a multi-display device + * + * @return Display that corresponds to the smaller display on a device or null if ther is only + * one Display on a device + */ + private Display getSmallerDisplayIfExists() { + List<Display> internalDisplays = getInternalDisplays(); + Point largestDisplaySize = getScreenDimensions(); + + // Find the first non-matching internal display + for (Display display : internalDisplays) { + Point displaySize = getRealSize(display); + if (displaySize.x != largestDisplaySize.x || displaySize.y != largestDisplaySize.y) { + return display; + } + } + + // If no smaller display found, return null, as there is only a single display + return null; + } + + /** + * This method retrieves the collection of Display objects available in the device. + * i.e. non-external displays are ignored + * + * @return list of displays corresponding to each display in the device + */ + private List<Display> getInternalDisplays() { + Display[] allDisplays = mDisplayManager.getDisplays( + DisplayManager.DISPLAY_CATEGORY_ALL_INCLUDING_DISABLED); + + List<Display> internalDisplays = new ArrayList<>(); + for (Display display : allDisplays) { + if (display.getType() == Display.TYPE_INTERNAL) { + internalDisplays.add(display); + } + } + return internalDisplays; + } + + /** + * This method compares the source and target dimensions, and returns true if there is a + * significant difference in area between them and the source dimensions are smaller than the + * target dimensions. + * + * @param sourceDimensions is the dimensions of the source device + * @param targetDimensions is the dimensions of the target device + */ + @VisibleForTesting + boolean isSourceDeviceSignificantlySmallerThanTarget(Point sourceDimensions, + Point targetDimensions) { + int rawAreaDelta = (targetDimensions.x * targetDimensions.y) + - (sourceDimensions.x * sourceDimensions.y); + return rawAreaDelta > AREA_THRESHOLD; + } + @VisibleForTesting boolean isDeviceInRestore() { try { diff --git a/packages/WallpaperBackup/test/src/com/android/wallpaperbackup/WallpaperBackupAgentTest.java b/packages/WallpaperBackup/test/src/com/android/wallpaperbackup/WallpaperBackupAgentTest.java index 3ecdf3f101a5..ec9223c7d667 100644 --- a/packages/WallpaperBackup/test/src/com/android/wallpaperbackup/WallpaperBackupAgentTest.java +++ b/packages/WallpaperBackup/test/src/com/android/wallpaperbackup/WallpaperBackupAgentTest.java @@ -59,6 +59,7 @@ import android.content.Context; import android.content.Intent; import android.content.pm.PackageManager; import android.content.pm.ResolveInfo; +import android.graphics.Point; import android.graphics.Rect; import android.os.FileUtils; import android.os.ParcelFileDescriptor; @@ -840,6 +841,26 @@ public class WallpaperBackupAgentTest { testParseCropHints(testMap); } + @Test + public void test_sourceDimensionsAreLargerThanTarget() { + // source device is larger than target, expecting to get false + Point sourceDimensions = new Point(2208, 1840); + Point targetDimensions = new Point(1080, 2092); + boolean isSourceSmaller = mWallpaperBackupAgent + .isSourceDeviceSignificantlySmallerThanTarget(sourceDimensions, targetDimensions); + assertThat(isSourceSmaller).isEqualTo(false); + } + + @Test + public void test_sourceDimensionsMuchSmallerThanTarget() { + // source device is smaller than target, expecting to get true + Point sourceDimensions = new Point(1080, 2092); + Point targetDimensions = new Point(2208, 1840); + boolean isSourceSmaller = mWallpaperBackupAgent + .isSourceDeviceSignificantlySmallerThanTarget(sourceDimensions, targetDimensions); + assertThat(isSourceSmaller).isEqualTo(true); + } + private void testParseCropHints(Map<Integer, Rect> testMap) throws Exception { assumeTrue(multiCrop()); mockRestoredStaticWallpaperFile(testMap); |