99import static io .github .muntashirakon .AppManager .backup .BackupManager .MASTER_KEY ;
1010import static io .github .muntashirakon .AppManager .backup .BackupManager .SOURCE_PREFIX ;
1111import static io .github .muntashirakon .AppManager .backup .BackupManager .getExt ;
12+ import static io .github .muntashirakon .AppManager .backup .BackupUtils .TAR_TYPES ;
1213import static io .github .muntashirakon .AppManager .compat .PackageManagerCompat .GET_SIGNING_CERTIFICATES ;
1314
1415import android .annotation .UserIdInt ;
2627import androidx .annotation .NonNull ;
2728import androidx .annotation .Nullable ;
2829import androidx .annotation .WorkerThread ;
30+ import androidx .core .content .pm .PackageInfoCompat ;
2931import androidx .core .content .pm .PermissionInfoCompat ;
3032
3133import java .io .Closeable ;
34+ import java .io .File ;
3235import java .io .FileNotFoundException ;
3336import java .io .IOException ;
3437import java .io .OutputStream ;
3841import java .util .List ;
3942import 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 ;
4148import io .github .muntashirakon .AppManager .compat .AppOpsManagerCompat ;
4249import io .github .muntashirakon .AppManager .compat .DeviceIdleManagerCompat ;
4350import io .github .muntashirakon .AppManager .compat .ManifestCompat ;
7178import io .github .muntashirakon .AppManager .utils .TarUtils ;
7279import io .github .muntashirakon .AppManager .utils .UIUtils ;
7380import io .github .muntashirakon .AppManager .utils .Utils ;
81+ import io .github .muntashirakon .compat .ObjectsCompat ;
7482import io .github .muntashirakon .io .IoUtils ;
7583import io .github .muntashirakon .io .Path ;
7684import 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