diff options
| author | 2023-06-05 16:40:27 +0000 | |
|---|---|---|
| committer | 2023-06-05 16:40:27 +0000 | |
| commit | 6906686d7daf91a02811fd055c1be683c769b51a (patch) | |
| tree | e4140f488d664253fc23a36e09942c0b4a791955 | |
| parent | 3198236b828283f557b382a488de304c29ac25ed (diff) | |
| parent | cf0b30b786bc2edfae5192a28feedba50ed13b1e (diff) | |
Merge "Add a backup and restore logic to ShortcutPackageItems"
5 files changed, 110 insertions, 112 deletions
diff --git a/services/core/java/com/android/server/pm/ShortcutLauncher.java b/services/core/java/com/android/server/pm/ShortcutLauncher.java index 00f7dc4025e6..bac300d4dd09 100644 --- a/services/core/java/com/android/server/pm/ShortcutLauncher.java +++ b/services/core/java/com/android/server/pm/ShortcutLauncher.java @@ -23,7 +23,6 @@ import android.content.pm.ShortcutInfo; import android.content.pm.UserPackage; import android.util.ArrayMap; import android.util.ArraySet; -import android.util.AtomicFile; import android.util.Slog; import android.util.Xml; @@ -32,8 +31,6 @@ import com.android.modules.utils.TypedXmlPullParser; import com.android.modules.utils.TypedXmlSerializer; import com.android.server.pm.ShortcutService.DumpFilter; -import libcore.io.IoUtils; - import org.json.JSONException; import org.json.JSONObject; import org.xmlpull.v1.XmlPullParser; @@ -41,7 +38,6 @@ import org.xmlpull.v1.XmlPullParserException; import java.io.File; import java.io.FileInputStream; -import java.io.FileNotFoundException; import java.io.IOException; import java.io.PrintWriter; import java.util.ArrayList; @@ -264,45 +260,41 @@ class ShortcutLauncher extends ShortcutPackageItem { public static ShortcutLauncher loadFromFile(File path, ShortcutUser shortcutUser, int ownerUserId, boolean fromBackup) { + try (ResilientAtomicFile file = getResilientFile(path)) { + FileInputStream in = null; + try { + in = file.openRead(); + if (in == null) { + Slog.d(TAG, "Not found " + path); + return null; + } - final AtomicFile file = new AtomicFile(path); - final FileInputStream in; - try { - in = file.openRead(); - } catch (FileNotFoundException e) { - if (ShortcutService.DEBUG) { - Slog.d(TAG, "Not found " + path); - } - return null; - } - - try { - ShortcutLauncher ret = null; - TypedXmlPullParser parser = Xml.resolvePullParser(in); + ShortcutLauncher ret = null; + TypedXmlPullParser parser = Xml.resolvePullParser(in); - int type; - while ((type = parser.next()) != XmlPullParser.END_DOCUMENT) { - if (type != XmlPullParser.START_TAG) { - continue; - } - final int depth = parser.getDepth(); + int type; + while ((type = parser.next()) != XmlPullParser.END_DOCUMENT) { + if (type != XmlPullParser.START_TAG) { + continue; + } + final int depth = parser.getDepth(); - final String tag = parser.getName(); - if (ShortcutService.DEBUG_LOAD) { - Slog.d(TAG, String.format("depth=%d type=%d name=%s", depth, type, tag)); - } - if ((depth == 1) && TAG_ROOT.equals(tag)) { - ret = loadFromXml(parser, shortcutUser, ownerUserId, fromBackup); - continue; + final String tag = parser.getName(); + if (ShortcutService.DEBUG_LOAD) { + Slog.d(TAG, String.format("depth=%d type=%d name=%s", depth, type, tag)); + } + if ((depth == 1) && TAG_ROOT.equals(tag)) { + ret = loadFromXml(parser, shortcutUser, ownerUserId, fromBackup); + continue; + } + ShortcutService.throwForInvalidTag(depth, tag); } - ShortcutService.throwForInvalidTag(depth, tag); + return ret; + } catch (Exception e) { + Slog.e(TAG, "Failed to read file " + file.getBaseFile(), e); + file.failRead(in, e); + return loadFromFile(path, shortcutUser, ownerUserId, fromBackup); } - return ret; - } catch (IOException | XmlPullParserException e) { - Slog.e(TAG, "Failed to read file " + file.getBaseFile(), e); - return null; - } finally { - IoUtils.closeQuietly(in); } } diff --git a/services/core/java/com/android/server/pm/ShortcutPackage.java b/services/core/java/com/android/server/pm/ShortcutPackage.java index 28cb7f0b03a6..0ea45c466ca7 100644 --- a/services/core/java/com/android/server/pm/ShortcutPackage.java +++ b/services/core/java/com/android/server/pm/ShortcutPackage.java @@ -50,7 +50,6 @@ import android.os.StrictMode; import android.text.format.Formatter; import android.util.ArrayMap; import android.util.ArraySet; -import android.util.AtomicFile; import android.util.Log; import android.util.Slog; import android.util.Xml; @@ -69,8 +68,6 @@ import com.android.server.pm.ShortcutService.DumpFilter; import com.android.server.pm.ShortcutService.ShortcutOperation; import com.android.server.pm.ShortcutService.Stats; -import libcore.io.IoUtils; - import org.json.JSONException; import org.json.JSONObject; import org.xmlpull.v1.XmlPullParser; @@ -78,7 +75,6 @@ import org.xmlpull.v1.XmlPullParserException; import java.io.File; import java.io.FileInputStream; -import java.io.FileNotFoundException; import java.io.IOException; import java.io.PrintWriter; import java.util.ArrayList; @@ -1969,45 +1965,41 @@ class ShortcutPackage extends ShortcutPackageItem { public static ShortcutPackage loadFromFile(ShortcutService s, ShortcutUser shortcutUser, File path, boolean fromBackup) { + try (ResilientAtomicFile file = getResilientFile(path)) { + FileInputStream in = null; + try { + in = file.openRead(); + if (in == null) { + Slog.d(TAG, "Not found " + path); + return null; + } - final AtomicFile file = new AtomicFile(path); - final FileInputStream in; - try { - in = file.openRead(); - } catch (FileNotFoundException e) { - if (ShortcutService.DEBUG) { - Slog.d(TAG, "Not found " + path); - } - return null; - } - - try { - ShortcutPackage ret = null; - TypedXmlPullParser parser = Xml.resolvePullParser(in); + ShortcutPackage ret = null; + TypedXmlPullParser parser = Xml.resolvePullParser(in); - int type; - while ((type = parser.next()) != XmlPullParser.END_DOCUMENT) { - if (type != XmlPullParser.START_TAG) { - continue; - } - final int depth = parser.getDepth(); + int type; + while ((type = parser.next()) != XmlPullParser.END_DOCUMENT) { + if (type != XmlPullParser.START_TAG) { + continue; + } + final int depth = parser.getDepth(); - final String tag = parser.getName(); - if (ShortcutService.DEBUG_LOAD || ShortcutService.DEBUG_REBOOT) { - Slog.d(TAG, String.format("depth=%d type=%d name=%s", depth, type, tag)); - } - if ((depth == 1) && TAG_ROOT.equals(tag)) { - ret = loadFromXml(s, shortcutUser, parser, fromBackup); - continue; + final String tag = parser.getName(); + if (ShortcutService.DEBUG_LOAD || ShortcutService.DEBUG_REBOOT) { + Slog.d(TAG, String.format("depth=%d type=%d name=%s", depth, type, tag)); + } + if ((depth == 1) && TAG_ROOT.equals(tag)) { + ret = loadFromXml(s, shortcutUser, parser, fromBackup); + continue; + } + ShortcutService.throwForInvalidTag(depth, tag); } - ShortcutService.throwForInvalidTag(depth, tag); + return ret; + } catch (Exception e) { + Slog.e(TAG, "Failed to read file " + file.getBaseFile(), e); + file.failRead(in, e); + return loadFromFile(s, shortcutUser, path, fromBackup); } - return ret; - } catch (IOException | XmlPullParserException e) { - Slog.e(TAG, "Failed to read file " + file.getBaseFile(), e); - return null; - } finally { - IoUtils.closeQuietly(in); } } diff --git a/services/core/java/com/android/server/pm/ShortcutPackageItem.java b/services/core/java/com/android/server/pm/ShortcutPackageItem.java index 8b118da1cdbe..8667888fbb51 100644 --- a/services/core/java/com/android/server/pm/ShortcutPackageItem.java +++ b/services/core/java/com/android/server/pm/ShortcutPackageItem.java @@ -20,14 +20,13 @@ import android.annotation.Nullable; import android.content.pm.PackageInfo; import android.content.pm.ShortcutInfo; import android.graphics.Bitmap; -import android.util.AtomicFile; +import android.os.FileUtils; import android.util.Slog; import android.util.Xml; import com.android.internal.annotations.GuardedBy; import com.android.internal.util.Preconditions; import com.android.modules.utils.TypedXmlSerializer; -import com.android.server.security.FileIntegrity; import org.json.JSONException; import org.json.JSONObject; @@ -160,36 +159,31 @@ abstract class ShortcutPackageItem { @GuardedBy("mLock") public void saveToFileLocked(File path, boolean forBackup) { - final AtomicFile file = new AtomicFile(path); - FileOutputStream os = null; - try { - os = file.startWrite(); - - // Write to XML - final TypedXmlSerializer itemOut; - if (forBackup) { - itemOut = Xml.newFastSerializer(); - itemOut.setOutput(os, StandardCharsets.UTF_8.name()); - } else { - itemOut = Xml.resolveSerializer(os); - } - itemOut.startDocument(null, true); - - saveToXml(itemOut, forBackup); - - itemOut.endDocument(); - - os.flush(); - file.finishWrite(os); - + try (ResilientAtomicFile file = getResilientFile(path)) { + FileOutputStream os = null; try { - FileIntegrity.setUpFsVerity(path); - } catch (IOException e) { - Slog.e(TAG, "Failed to verity-protect " + path, e); + os = file.startWrite(); + + // Write to XML + final TypedXmlSerializer itemOut; + if (forBackup) { + itemOut = Xml.newFastSerializer(); + itemOut.setOutput(os, StandardCharsets.UTF_8.name()); + } else { + itemOut = Xml.resolveSerializer(os); + } + itemOut.startDocument(null, true); + + saveToXml(itemOut, forBackup); + + itemOut.endDocument(); + + os.flush(); + file.finishWrite(os); + } catch (XmlPullParserException | IOException e) { + Slog.e(TAG, "Failed to write to file " + file.getBaseFile(), e); + file.failWrite(os); } - } catch (XmlPullParserException | IOException e) { - Slog.e(TAG, "Failed to write to file " + file.getBaseFile(), e); - file.failWrite(os); } } @@ -265,9 +259,18 @@ abstract class ShortcutPackageItem { void removeShortcutPackageItem() { synchronized (mLock) { - getShortcutPackageItemFile().delete(); + getResilientFile(getShortcutPackageItemFile()).delete(); } } protected abstract File getShortcutPackageItemFile(); + + protected static ResilientAtomicFile getResilientFile(File file) { + String path = file.getPath(); + File temporaryBackup = new File(path + ".backup"); + File reserveCopy = new File(path + ".reservecopy"); + int fileMode = FileUtils.S_IRWXU | FileUtils.S_IRWXG | FileUtils.S_IXOTH; + return new ResilientAtomicFile(file, temporaryBackup, reserveCopy, fileMode, + "shortcut package item", null); + } } diff --git a/services/core/java/com/android/server/pm/ShortcutUser.java b/services/core/java/com/android/server/pm/ShortcutUser.java index 94eb6bb25caa..d32eb22afb61 100644 --- a/services/core/java/com/android/server/pm/ShortcutUser.java +++ b/services/core/java/com/android/server/pm/ShortcutUser.java @@ -437,14 +437,14 @@ class ShortcutUser { } else { final File root = s.injectUserDataPath(userId); - forAllFilesIn(new File(root, DIRECTORY_PACKAGES), (File f) -> { + forMainFilesIn(new File(root, DIRECTORY_PACKAGES), (File f) -> { final ShortcutPackage sp = ShortcutPackage.loadFromFile(s, ret, f, fromBackup); if (sp != null) { ret.mPackages.put(sp.getPackageName(), sp); } }); - forAllFilesIn(new File(root, DIRECTORY_LUANCHERS), (File f) -> { + forMainFilesIn(new File(root, DIRECTORY_LUANCHERS), (File f) -> { final ShortcutLauncher sl = ShortcutLauncher.loadFromFile(f, ret, userId, fromBackup); if (sl != null) { @@ -456,13 +456,15 @@ class ShortcutUser { return ret; } - private static void forAllFilesIn(File path, Consumer<File> callback) { + private static void forMainFilesIn(File path, Consumer<File> callback) { if (!path.exists()) { return; } File[] list = path.listFiles(); for (File f : list) { - callback.accept(f); + if (!f.getName().endsWith(".reservecopy") && !f.getName().endsWith(".backup")) { + callback.accept(f); + } } } diff --git a/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest1.java b/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest1.java index 7c1845fcd54e..0f5fb91a140f 100644 --- a/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest1.java +++ b/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest1.java @@ -125,6 +125,8 @@ import java.io.InputStreamReader; import java.io.OutputStream; import java.io.Writer; import java.nio.charset.StandardCharsets; +import java.nio.file.Files; +import java.nio.file.StandardCopyOption; import java.util.ArrayList; import java.util.List; import java.util.Locale; @@ -4014,8 +4016,10 @@ public class ShortcutManagerTest1 extends BaseShortcutManagerTest { ShortcutUser user = new ShortcutUser(mService, 0); - File corruptedShortcutPackage = new File("/data/local/tmp/cts/content/", + File corruptedShortcutPackage = new File(getTestContext().getFilesDir(), "broken_shortcut.xml"); + Files.copy(new File("/data/local/tmp/cts/content/", "broken_shortcut.xml").toPath(), + corruptedShortcutPackage.toPath(), StandardCopyOption.REPLACE_EXISTING); assertNull(ShortcutPackage.loadFromFile(mService, user, corruptedShortcutPackage, false)); } @@ -4116,6 +4120,11 @@ public class ShortcutManagerTest1 extends BaseShortcutManagerTest { try (Writer os = new FileWriter(mService.getUserFile(USER_10).getBaseFile())) { os.write("<?xml version='1.0' encoding='utf"); } + ShortcutPackage sp = mService.getUserShortcutsLocked(USER_0).getPackageShortcutsIfExists( + CALLING_PACKAGE_1); + try (Writer os = new FileWriter(sp.getShortcutPackageItemFile().getPath())) { + os.write("<?xml version='1.0' encoding='utf"); + } // Restore. initService(); |