Skip to content

Commit 7bc31a1

Browse files
committed
refactor: move MetadataManager.Metadata to BackupMetadataV2
Signed-off-by: Muntashir Al-Islam <muntashirakon@riseup.net>
1 parent 8c5e656 commit 7bc31a1

20 files changed

Lines changed: 499 additions & 528 deletions

app/src/main/java/io/github/muntashirakon/AppManager/backup/BackupItems.java

Lines changed: 36 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,10 @@
22

33
package io.github.muntashirakon.AppManager.backup;
44

5+
import static io.github.muntashirakon.AppManager.backup.BackupManager.DATA_PREFIX;
6+
import static io.github.muntashirakon.AppManager.backup.BackupManager.KEYSTORE_PREFIX;
7+
import static io.github.muntashirakon.AppManager.backup.BackupManager.SOURCE_PREFIX;
8+
59
import androidx.annotation.NonNull;
610
import androidx.annotation.Nullable;
711

@@ -17,6 +21,7 @@
1721
import java.util.List;
1822
import java.util.stream.Collectors;
1923

24+
import io.github.muntashirakon.AppManager.backup.struct.BackupMetadataV2;
2025
import io.github.muntashirakon.AppManager.crypto.Crypto;
2126
import io.github.muntashirakon.AppManager.crypto.DummyCrypto;
2227
import io.github.muntashirakon.AppManager.logcat.helper.SaveLogHelper;
@@ -25,11 +30,10 @@
2530
import io.github.muntashirakon.io.Path;
2631
import io.github.muntashirakon.io.PathReader;
2732
import io.github.muntashirakon.io.PathWriter;
33+
import io.github.muntashirakon.io.Paths;
2834

2935
public class BackupItems {
3036
private static final String APK_SAVING_DIRECTORY = "apks";
31-
@Deprecated // No longer used
32-
private static final String TEMPORARY_DIRECTORY = ".tmp";
3337

3438
private static final String ICON_FILE = "icon.png";
3539
private static final String RULES_TSV = "rules.am.tsv";
@@ -73,7 +77,7 @@ public static List<BackupItem> findAllBackupItems() {
7377
if (APK_SAVING_DIRECTORY.equals(path.getName())) {
7478
continue;
7579
}
76-
if (TEMPORARY_DIRECTORY.equals(path.getName())) {
80+
if (".tmp".equals(path.getName())) {
7781
continue;
7882
}
7983
// Other backups can store multiple backups per folder
@@ -270,11 +274,15 @@ public Path getIconFile() throws IOException {
270274
}
271275

272276
@NonNull
273-
public Path getMetadataFile() throws IOException {
277+
public Path getMetadataV2File() throws IOException {
274278
// meta is never encrypted
275279
if (mBackupMode) {
276-
return getBackupPath().findOrCreateFile(MetadataManager.META_FILE, null);
277-
} else return getBackupPath().findFile(MetadataManager.META_FILE);
280+
return getBackupPath().findOrCreateFile(MetadataManager.META_V2_FILE, null);
281+
} else return getBackupPath().findFile(MetadataManager.META_V2_FILE);
282+
}
283+
284+
public BackupMetadataV2 getMetadataV2() throws IOException {
285+
return MetadataManager.readMetadataV2(this);
278286
}
279287

280288
@NonNull
@@ -316,6 +324,28 @@ public Path getRulesFile() throws IOException {
316324
}
317325
}
318326

327+
@NonNull
328+
public Path[] getSourceFiles() {
329+
String ext = CryptoUtils.getExtension(mCryptoMode);
330+
Path[] paths = getBackupPath().listFiles((dir, name) -> name.startsWith(SOURCE_PREFIX) && name.endsWith(ext));
331+
return Paths.getSortedPaths(paths);
332+
}
333+
334+
@NonNull
335+
public Path[] getDataFiles(int index) {
336+
String ext = CryptoUtils.getExtension(mCryptoMode);
337+
final String dataPrefix = DATA_PREFIX + index;
338+
Path[] paths = getBackupPath().listFiles((dir, name) -> name.startsWith(dataPrefix) && name.endsWith(ext));
339+
return Paths.getSortedPaths(paths);
340+
}
341+
342+
@NonNull
343+
public Path[] getKeyStoreFiles() {
344+
String ext = CryptoUtils.getExtension(mCryptoMode);
345+
Path[] paths = getBackupPath().listFiles((dir, name) -> name.startsWith(KEYSTORE_PREFIX) && name.endsWith(ext));
346+
return Paths.getSortedPaths(paths);
347+
}
348+
319349
public void freeze() throws IOException {
320350
getBackupPath().createNewFile(FREEZE, null);
321351
}

app/src/main/java/io/github/muntashirakon/AppManager/backup/BackupManager.java

Lines changed: 16 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -8,11 +8,13 @@
88
import java.io.IOException;
99
import java.util.Arrays;
1010

11+
import io.github.muntashirakon.AppManager.backup.struct.BackupMetadataV2;
1112
import io.github.muntashirakon.AppManager.logs.Log;
1213
import io.github.muntashirakon.AppManager.progress.ProgressHandler;
1314
import io.github.muntashirakon.AppManager.types.UserPackagePair;
1415
import io.github.muntashirakon.AppManager.utils.ContextUtils;
1516
import io.github.muntashirakon.AppManager.utils.DateUtils;
17+
import io.github.muntashirakon.AppManager.utils.ExUtils;
1618
import io.github.muntashirakon.AppManager.utils.TarUtils;
1719

1820
/**
@@ -35,9 +37,11 @@ public class BackupManager {
3537

3638
@NonNull
3739
public static String getExt(@TarUtils.TarType String tarType) {
38-
if (TarUtils.TAR_BZIP2.equals(tarType)) return ".tar.bz2";
39-
if (TarUtils.TAR_ZSTD.equals(tarType)) return ".tar.zst";
40-
else return ".tar.gz";
40+
if (TarUtils.TAR_BZIP2.equals(tarType)) {
41+
return ".tar.bz2";
42+
} else if (TarUtils.TAR_ZSTD.equals(tarType)) {
43+
return ".tar.zst";
44+
} else return ".tar.gz";
4145
}
4246

4347
/**
@@ -53,21 +57,14 @@ public static BackupManager getNewInstance(UserPackagePair targetPackage, int fl
5357
@NonNull
5458
private final UserPackagePair mTargetPackage;
5559
@NonNull
56-
private final MetadataManager mMetadataManager;
57-
@NonNull
5860
private final BackupFlags mRequestedFlags;
5961

6062
private boolean mRequiresRestart;
6163

6264
protected BackupManager(@NonNull UserPackagePair targetPackage, int flags) {
6365
mTargetPackage = targetPackage;
64-
mMetadataManager = MetadataManager.getNewInstance();
6566
mRequestedFlags = new BackupFlags(flags);
66-
try {
67-
BackupItems.createNoMediaIfNotExists();
68-
} catch (IOException e) {
69-
e.printStackTrace();
70-
}
67+
ExUtils.exceptionAsIgnored(BackupItems::createNoMediaIfNotExists);
7168
Log.d(TAG, "Package: %s, user: %d", targetPackage.getPackageName(), targetPackage.getUserId());
7269
}
7370

@@ -99,8 +96,8 @@ public void backup(@Nullable String[] backupNames, @Nullable ProgressHandler pro
9996
progressHandler.postUpdate(max, 0f);
10097
}
10198
for (BackupItems.BackupItem backupItem : backupItemList) {
102-
try (BackupOp backupOp = new BackupOp(mTargetPackage.getPackageName(), mMetadataManager, mRequestedFlags,
103-
backupItem, mTargetPackage.getUserId())) {
99+
try (BackupOp backupOp = new BackupOp(mTargetPackage.getPackageName(),
100+
mRequestedFlags, backupItem, mTargetPackage.getUserId())) {
104101
backupOp.runBackup(progressHandler);
105102
BackupUtils.putBackupToDbAndBroadcast(ContextUtils.getContext(), backupOp.getMetadata());
106103
}
@@ -183,7 +180,7 @@ public void restore(@Nullable String[] backupNames, @Nullable ProgressHandler pr
183180
progressHandler.postUpdate(max, 0f);
184181
}
185182
try (RestoreOp restoreOp = new RestoreOp(mTargetPackage.getPackageName(),
186-
mMetadataManager, mRequestedFlags, backupItemList[0],
183+
mRequestedFlags, backupItemList[0],
187184
mTargetPackage.getUserId())) {
188185
restoreOp.runRestore(progressHandler);
189186
mRequiresRestart |= restoreOp.requiresRestart();
@@ -207,7 +204,7 @@ public void deleteBackup(@Nullable String[] backupNames) throws BackupException
207204
}
208205
for (BackupItems.BackupItem backupItem : backupItemList) {
209206
try {
210-
MetadataManager.Metadata metadata = MetadataManager.getMetadata(backupItem);
207+
BackupMetadataV2 metadata = backupItem.getMetadataV2();
211208
if (!backupItem.isFrozen() && !backupItem.delete()) {
212209
throw new BackupException("Could not delete the selected backups");
213210
}
@@ -219,12 +216,12 @@ public void deleteBackup(@Nullable String[] backupNames) throws BackupException
219216
} else {
220217
// backupNames is not null but that doesn't mean that it's not empty,
221218
// requested for only single backups
222-
BackupItems.BackupItem backupItem;
223219
for (String backupName : backupNames) {
224-
MetadataManager.Metadata metadata;
220+
BackupItems.BackupItem backupItem;
221+
BackupMetadataV2 metadata;
225222
try {
226223
backupItem = BackupItems.findBackupItem(backupName, mTargetPackage.getPackageName(), null);
227-
metadata = MetadataManager.getMetadata(backupItem);
224+
metadata = backupItem.getMetadataV2();
228225
} catch (IOException e) {
229226
throw new BackupException("Could not get backup files.", e);
230227
}
@@ -261,7 +258,7 @@ public void verify(@Nullable String backupName) throws BackupException {
261258
if (backupItemList.length > 1) {
262259
Log.w(VerifyOp.TAG, "More than one backups found! Verifying only the first backup.");
263260
}
264-
try (VerifyOp restoreOp = new VerifyOp(mMetadataManager, backupItemList[0])) {
261+
try (VerifyOp restoreOp = new VerifyOp(backupItemList[0])) {
265262
restoreOp.verify();
266263
}
267264
} else {

app/src/main/java/io/github/muntashirakon/AppManager/backup/BackupOp.java

Lines changed: 69 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
import static io.github.muntashirakon.AppManager.backup.BackupManager.MASTER_KEY;
1010
import static io.github.muntashirakon.AppManager.backup.BackupManager.SOURCE_PREFIX;
1111
import static io.github.muntashirakon.AppManager.backup.BackupManager.getExt;
12+
import static io.github.muntashirakon.AppManager.backup.BackupUtils.TAR_TYPES;
1213
import static io.github.muntashirakon.AppManager.compat.PackageManagerCompat.GET_SIGNING_CERTIFICATES;
1314

1415
import android.annotation.UserIdInt;
@@ -26,9 +27,11 @@
2627
import androidx.annotation.NonNull;
2728
import androidx.annotation.Nullable;
2829
import androidx.annotation.WorkerThread;
30+
import androidx.core.content.pm.PackageInfoCompat;
2931
import androidx.core.content.pm.PermissionInfoCompat;
3032

3133
import java.io.Closeable;
34+
import java.io.File;
3235
import java.io.FileNotFoundException;
3336
import java.io.IOException;
3437
import java.io.OutputStream;
@@ -38,6 +41,10 @@
3841
import java.util.List;
3942
import java.util.regex.Pattern;
4043

44+
import io.github.muntashirakon.AppManager.BuildConfig;
45+
import io.github.muntashirakon.AppManager.apk.ApkFile;
46+
import io.github.muntashirakon.AppManager.apk.ApkSource;
47+
import io.github.muntashirakon.AppManager.backup.struct.BackupMetadataV2;
4148
import io.github.muntashirakon.AppManager.compat.AppOpsManagerCompat;
4249
import io.github.muntashirakon.AppManager.compat.DeviceIdleManagerCompat;
4350
import io.github.muntashirakon.AppManager.compat.ManifestCompat;
@@ -71,6 +78,7 @@
7178
import io.github.muntashirakon.AppManager.utils.TarUtils;
7279
import io.github.muntashirakon.AppManager.utils.UIUtils;
7380
import io.github.muntashirakon.AppManager.utils.Utils;
81+
import io.github.muntashirakon.compat.ObjectsCompat;
7482
import io.github.muntashirakon.io.IoUtils;
7583
import io.github.muntashirakon.io.Path;
7684
import io.github.muntashirakon.io.Paths;
@@ -84,11 +92,9 @@ class BackupOp implements Closeable {
8492
@NonNull
8593
private final BackupItems.BackupItem mBackupItem;
8694
@NonNull
87-
private final MetadataManager mMetadataManager;
88-
@NonNull
8995
private final BackupFlags mBackupFlags;
9096
@NonNull
91-
private final MetadataManager.Metadata mMetadata;
97+
private final BackupMetadataV2 mMetadata;
9298
@NonNull
9399
private final PackageInfo mPackageInfo;
94100
@NonNull
@@ -101,12 +107,12 @@ class BackupOp implements Closeable {
101107
@NonNull
102108
private final PackageManager mPm;
103109

104-
BackupOp(@NonNull String packageName, @NonNull MetadataManager metadataManager, @NonNull BackupFlags backupFlags,
105-
@NonNull BackupItems.BackupItem backupItem, @UserIdInt int userId) throws BackupException {
110+
BackupOp(@NonNull String packageName, @NonNull BackupFlags backupFlags,
111+
@NonNull BackupItems.BackupItem backupItem, @UserIdInt int userId)
112+
throws BackupException {
106113
mPackageName = packageName;
107114
mBackupItem = backupItem;
108115
mUserId = userId;
109-
mMetadataManager = metadataManager;
110116
mBackupFlags = backupFlags;
111117
mPm = ContextUtils.getContext().getPackageManager();
112118
try {
@@ -115,7 +121,7 @@ class BackupOp implements Closeable {
115121
| PackageManagerCompat.MATCH_STATIC_SHARED_AND_SDK_LIBRARIES, userId);
116122
mApplicationInfo = mPackageInfo.applicationInfo;
117123
// Override existing metadata
118-
mMetadata = mMetadataManager.setupMetadata(mPackageInfo, userId, backupFlags);
124+
mMetadata = setupMetadata(mPackageInfo, userId, backupFlags);
119125
mMetadata.backupName = backupItem.backupName;
120126
} catch (Exception e) {
121127
mBackupItem.cleanup();
@@ -147,7 +153,7 @@ public void close() {
147153
}
148154

149155
@NonNull
150-
public MetadataManager.Metadata getMetadata() {
156+
public BackupMetadataV2 getMetadata() {
151157
return mMetadata;
152158
}
153159

@@ -187,16 +193,15 @@ void runBackup(@Nullable ProgressHandler progressHandler) throws BackupException
187193
// Set backup time
188194
mMetadata.backupTime = System.currentTimeMillis();
189195
// Write modified metadata
190-
mMetadataManager.setMetadata(mMetadata);
191196
try {
192-
mMetadataManager.writeMetadata(mBackupItem);
197+
MetadataManager.writeMetadataV2(mMetadata, mBackupItem);
193198
} catch (IOException e) {
194199
throw new BackupException("Failed to write metadata.", e);
195200
}
196201
// Store checksum for metadata
197202
try {
198-
mChecksum.add(MetadataManager.META_FILE, DigestUtils.getHexDigest(mMetadata.checksumAlgo,
199-
mBackupItem.getMetadataFile()));
203+
mChecksum.add(MetadataManager.META_V2_FILE, DigestUtils.getHexDigest(mMetadata.checksumAlgo,
204+
mBackupItem.getMetadataV2File()));
200205
} catch (IOException e) {
201206
throw new BackupException("Failed to generate checksum for meta.json", e);
202207
} finally {
@@ -229,6 +234,58 @@ private static void incrementProgress(@Nullable ProgressHandler progressHandler)
229234
progressHandler.postUpdate(current);
230235
}
231236

237+
public BackupMetadataV2 setupMetadata(@NonNull PackageInfo packageInfo,
238+
@UserIdInt int userHandle,
239+
@NonNull BackupFlags requestedFlags) {
240+
ApplicationInfo applicationInfo = packageInfo.applicationInfo;
241+
BackupMetadataV2 metadata = new BackupMetadataV2();
242+
// We don't need to backup custom users or multiple backup flags
243+
requestedFlags.removeFlag(BackupFlags.BACKUP_CUSTOM_USERS | BackupFlags.BACKUP_MULTIPLE);
244+
metadata.flags = requestedFlags;
245+
metadata.userHandle = userHandle;
246+
metadata.tarType = Prefs.BackupRestore.getCompressionMethod();
247+
metadata.crypto = CryptoUtils.getMode();
248+
// Verify tar type
249+
if (ArrayUtils.indexOf(TAR_TYPES, metadata.tarType) == -1) {
250+
// Unknown tar type, set default
251+
metadata.tarType = TarUtils.TAR_GZIP;
252+
}
253+
metadata.keyStore = KeyStoreUtils.hasKeyStore(applicationInfo.uid);
254+
metadata.label = applicationInfo.loadLabel(mPm).toString();
255+
metadata.packageName = packageInfo.packageName;
256+
metadata.versionName = packageInfo.versionName;
257+
metadata.versionCode = PackageInfoCompat.getLongVersionCode(packageInfo);
258+
metadata.apkName = new File(applicationInfo.sourceDir).getName();
259+
metadata.dataDirs = BackupUtils.getDataDirectories(applicationInfo, requestedFlags.backupInternalData(),
260+
requestedFlags.backupExternalData(), requestedFlags.backupMediaObb());
261+
metadata.isSystem = (applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0;
262+
metadata.isSplitApk = false;
263+
try (ApkFile apkFile = ApkSource.getApkSource(applicationInfo).resolve()) {
264+
if (apkFile.isSplit()) {
265+
List<ApkFile.Entry> apkEntries = apkFile.getEntries();
266+
int splitCount = apkEntries.size() - 1;
267+
metadata.isSplitApk = splitCount > 0;
268+
metadata.splitConfigs = new String[splitCount];
269+
for (int i = 0; i < splitCount; ++i) {
270+
metadata.splitConfigs[i] = apkEntries.get(i + 1).getFileName();
271+
}
272+
}
273+
} catch (ApkFile.ApkFileException e) {
274+
e.printStackTrace();
275+
}
276+
metadata.splitConfigs = ArrayUtils.defeatNullable(metadata.splitConfigs);
277+
metadata.hasRules = false;
278+
if (requestedFlags.backupRules()) {
279+
try (ComponentsBlocker cb = ComponentsBlocker.getInstance(packageInfo.packageName, userHandle, false)) {
280+
metadata.hasRules = cb.entryCount() > 0;
281+
}
282+
}
283+
metadata.backupTime = 0;
284+
metadata.installer = ObjectsCompat.requireNonNullElse(PackageManagerCompat.getInstallerPackageName(
285+
packageInfo.packageName, userHandle), BuildConfig.APPLICATION_ID);
286+
return metadata;
287+
}
288+
232289
private void backupIcon() {
233290
try {
234291
Path iconFile = mBackupItem.getIconFile();

0 commit comments

Comments
 (0)