RollbackManager: Backup and restore split apks.
Previously RollbackManager would only backup and restore the base apk for a package. This change fixes it to backup and restore split apks as well. Adds a new test for rollback of packages built with splits. Also, switch to using resources to distinguish between v1 and v2 of an application instead of meta-data, given we use resources anyway now to distinguish between split versions. Bug: 124848643 Test: atest RollbackTest, with new test for splits added. Change-Id: Id1f32db7b728bdeda6c7223bc69a7e80ba569dda
This commit is contained in:
@@ -23,6 +23,7 @@ import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.IntentFilter;
|
||||
import android.content.IntentSender;
|
||||
import android.content.pm.ApplicationInfo;
|
||||
import android.content.pm.PackageInfo;
|
||||
import android.content.pm.PackageInstaller;
|
||||
import android.content.pm.PackageManager;
|
||||
@@ -47,6 +48,7 @@ import android.util.SparseBooleanArray;
|
||||
import android.util.SparseLongArray;
|
||||
|
||||
import com.android.internal.annotations.GuardedBy;
|
||||
import com.android.internal.util.ArrayUtils;
|
||||
import com.android.server.LocalServices;
|
||||
import com.android.server.pm.Installer;
|
||||
|
||||
@@ -362,20 +364,24 @@ class RollbackManagerServiceImpl extends IRollbackManager.Stub {
|
||||
int sessionId = packageInstaller.createSession(params);
|
||||
PackageInstaller.Session session = packageInstaller.openSession(sessionId);
|
||||
|
||||
File packageCode = RollbackStore.getPackageCode(data, info.getPackageName());
|
||||
if (packageCode == null) {
|
||||
File[] packageCodePaths = RollbackStore.getPackageCodePaths(
|
||||
data, info.getPackageName());
|
||||
if (packageCodePaths == null) {
|
||||
sendFailure(statusReceiver, RollbackManager.STATUS_FAILURE,
|
||||
"Backup copy of package code inaccessible");
|
||||
"Backup copy of package inaccessible");
|
||||
return;
|
||||
}
|
||||
|
||||
try (ParcelFileDescriptor fd = ParcelFileDescriptor.open(packageCode,
|
||||
ParcelFileDescriptor.MODE_READ_ONLY)) {
|
||||
final long token = Binder.clearCallingIdentity();
|
||||
try {
|
||||
session.write(packageCode.getName(), 0, packageCode.length(), fd);
|
||||
} finally {
|
||||
Binder.restoreCallingIdentity(token);
|
||||
for (File packageCodePath : packageCodePaths) {
|
||||
try (ParcelFileDescriptor fd = ParcelFileDescriptor.open(packageCodePath,
|
||||
ParcelFileDescriptor.MODE_READ_ONLY)) {
|
||||
final long token = Binder.clearCallingIdentity();
|
||||
try {
|
||||
session.write(packageCodePath.getName(), 0, packageCodePath.length(),
|
||||
fd);
|
||||
} finally {
|
||||
Binder.restoreCallingIdentity(token);
|
||||
}
|
||||
}
|
||||
}
|
||||
parentSession.addChildSessionId(sessionId);
|
||||
@@ -950,7 +956,13 @@ class RollbackManagerServiceImpl extends IRollbackManager.Stub {
|
||||
}
|
||||
|
||||
try {
|
||||
RollbackStore.backupPackageCode(data, packageName, pkgInfo.applicationInfo.sourceDir);
|
||||
ApplicationInfo appInfo = pkgInfo.applicationInfo;
|
||||
RollbackStore.backupPackageCodePath(data, packageName, appInfo.sourceDir);
|
||||
if (!ArrayUtils.isEmpty(appInfo.splitSourceDirs)) {
|
||||
for (String sourceDir : appInfo.splitSourceDirs) {
|
||||
RollbackStore.backupPackageCodePath(data, packageName, sourceDir);
|
||||
}
|
||||
}
|
||||
} catch (IOException e) {
|
||||
Log.e(TAG, "Unable to copy package for rollback for " + packageName, e);
|
||||
return false;
|
||||
|
||||
@@ -234,9 +234,11 @@ class RollbackStore {
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a backup copy of the apk or apex for a package.
|
||||
* Creates a backup copy of an apk or apex for a package.
|
||||
* For packages containing splits, this method should be called for each
|
||||
* of the package's split apks in addition to the base apk.
|
||||
*/
|
||||
static void backupPackageCode(RollbackData data, String packageName, String codePath)
|
||||
static void backupPackageCodePath(RollbackData data, String packageName, String codePath)
|
||||
throws IOException {
|
||||
File sourceFile = new File(codePath);
|
||||
File targetDir = new File(data.backupDir, packageName);
|
||||
@@ -248,16 +250,16 @@ class RollbackStore {
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the apk or apex file backed up for the given package.
|
||||
* Returns null if none found.
|
||||
* Returns the apk or apex files backed up for the given package.
|
||||
* Includes the base apk and any splits. Returns null if none found.
|
||||
*/
|
||||
static File getPackageCode(RollbackData data, String packageName) {
|
||||
static File[] getPackageCodePaths(RollbackData data, String packageName) {
|
||||
File targetDir = new File(data.backupDir, packageName);
|
||||
File[] files = targetDir.listFiles();
|
||||
if (files == null || files.length != 1) {
|
||||
if (files == null || files.length == 0) {
|
||||
return null;
|
||||
}
|
||||
return files[0];
|
||||
return files;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -21,6 +21,7 @@ LOCAL_MODULE_PATH := $(TARGET_OUT_DATA_APPS)
|
||||
LOCAL_SDK_VERSION := current
|
||||
LOCAL_SRC_FILES := $(call all-java-files-under, TestApp/src)
|
||||
LOCAL_MANIFEST_FILE := TestApp/Av1.xml
|
||||
LOCAL_RESOURCE_DIR := $(LOCAL_PATH)/TestApp/res_v1
|
||||
LOCAL_PACKAGE_NAME := RollbackTestAppAv1
|
||||
include $(BUILD_PACKAGE)
|
||||
ROLLBACK_TEST_APP_AV1 := $(LOCAL_INSTALLED_MODULE)
|
||||
@@ -32,6 +33,7 @@ LOCAL_MODULE_PATH := $(TARGET_OUT_DATA_APPS)
|
||||
LOCAL_SDK_VERSION := current
|
||||
LOCAL_SRC_FILES := $(call all-java-files-under, TestApp/src)
|
||||
LOCAL_MANIFEST_FILE := TestApp/Av2.xml
|
||||
LOCAL_RESOURCE_DIR := $(LOCAL_PATH)/TestApp/res_v2
|
||||
LOCAL_PACKAGE_NAME := RollbackTestAppAv2
|
||||
include $(BUILD_PACKAGE)
|
||||
ROLLBACK_TEST_APP_AV2 := $(LOCAL_INSTALLED_MODULE)
|
||||
@@ -43,6 +45,7 @@ LOCAL_MODULE_PATH := $(TARGET_OUT_DATA_APPS)
|
||||
LOCAL_SDK_VERSION := current
|
||||
LOCAL_SRC_FILES := $(call all-java-files-under, TestApp/src)
|
||||
LOCAL_MANIFEST_FILE := TestApp/ACrashingV2.xml
|
||||
LOCAL_RESOURCE_DIR := $(LOCAL_PATH)/TestApp/res_v2
|
||||
LOCAL_PACKAGE_NAME := RollbackTestAppACrashingV2
|
||||
include $(BUILD_PACKAGE)
|
||||
ROLLBACK_TEST_APP_A_CRASHING_V2 := $(LOCAL_INSTALLED_MODULE)
|
||||
@@ -54,6 +57,7 @@ LOCAL_MODULE_PATH := $(TARGET_OUT_DATA_APPS)
|
||||
LOCAL_SDK_VERSION := current
|
||||
LOCAL_SRC_FILES := $(call all-java-files-under, TestApp/src)
|
||||
LOCAL_MANIFEST_FILE := TestApp/Bv1.xml
|
||||
LOCAL_RESOURCE_DIR := $(LOCAL_PATH)/TestApp/res_v1
|
||||
LOCAL_PACKAGE_NAME := RollbackTestAppBv1
|
||||
include $(BUILD_PACKAGE)
|
||||
ROLLBACK_TEST_APP_BV1 := $(LOCAL_INSTALLED_MODULE)
|
||||
@@ -65,10 +69,39 @@ LOCAL_MODULE_PATH := $(TARGET_OUT_DATA_APPS)
|
||||
LOCAL_SDK_VERSION := current
|
||||
LOCAL_SRC_FILES := $(call all-java-files-under, TestApp/src)
|
||||
LOCAL_MANIFEST_FILE := TestApp/Bv2.xml
|
||||
LOCAL_RESOURCE_DIR := $(LOCAL_PATH)/TestApp/res_v2
|
||||
LOCAL_PACKAGE_NAME := RollbackTestAppBv2
|
||||
include $(BUILD_PACKAGE)
|
||||
ROLLBACK_TEST_APP_BV2 := $(LOCAL_INSTALLED_MODULE)
|
||||
|
||||
# RollbackTestAppASplitV1.apk
|
||||
include $(CLEAR_VARS)
|
||||
LOCAL_MODULE_TAGS := optional
|
||||
LOCAL_MODULE_PATH := $(TARGET_OUT_DATA_APPS)
|
||||
LOCAL_SDK_VERSION := current
|
||||
LOCAL_SRC_FILES := $(call all-java-files-under, TestApp/src)
|
||||
LOCAL_MANIFEST_FILE := TestApp/Av1.xml
|
||||
LOCAL_RESOURCE_DIR := $(LOCAL_PATH)/TestApp/res_v1
|
||||
LOCAL_PACKAGE_NAME := RollbackTestAppASplitV1
|
||||
LOCAL_PACKAGE_SPLITS := anydpi
|
||||
include $(BUILD_PACKAGE)
|
||||
ROLLBACK_TEST_APP_A_SPLIT_V1 := $(LOCAL_INSTALLED_MODULE)
|
||||
ROLLBACK_TEST_APP_A_SPLIT_V1_SPLIT := $(installed_apk_splits)
|
||||
|
||||
# RollbackTestAppASplitV2.apk
|
||||
include $(CLEAR_VARS)
|
||||
LOCAL_MODULE_TAGS := optional
|
||||
LOCAL_MODULE_PATH := $(TARGET_OUT_DATA_APPS)
|
||||
LOCAL_SDK_VERSION := current
|
||||
LOCAL_SRC_FILES := $(call all-java-files-under, TestApp/src)
|
||||
LOCAL_MANIFEST_FILE := TestApp/Av2.xml
|
||||
LOCAL_RESOURCE_DIR := $(LOCAL_PATH)/TestApp/res_v2
|
||||
LOCAL_PACKAGE_NAME := RollbackTestAppASplitV2
|
||||
LOCAL_PACKAGE_SPLITS := anydpi
|
||||
include $(BUILD_PACKAGE)
|
||||
ROLLBACK_TEST_APP_A_SPLIT_V2 := $(LOCAL_INSTALLED_MODULE)
|
||||
ROLLBACK_TEST_APP_A_SPLIT_V2_SPLIT := $(installed_apk_splits)
|
||||
|
||||
# RollbackTest
|
||||
include $(CLEAR_VARS)
|
||||
LOCAL_SRC_FILES := $(call all-java-files-under, RollbackTest/src)
|
||||
@@ -82,6 +115,10 @@ LOCAL_JAVA_RESOURCE_FILES := \
|
||||
$(ROLLBACK_TEST_APP_A_CRASHING_V2) \
|
||||
$(ROLLBACK_TEST_APP_BV1) \
|
||||
$(ROLLBACK_TEST_APP_BV2) \
|
||||
$(ROLLBACK_TEST_APP_A_SPLIT_V1) \
|
||||
$(ROLLBACK_TEST_APP_A_SPLIT_V1_SPLIT) \
|
||||
$(ROLLBACK_TEST_APP_A_SPLIT_V2) \
|
||||
$(ROLLBACK_TEST_APP_A_SPLIT_V2_SPLIT) \
|
||||
$(ROLLBACK_TEST_APEX_V1) \
|
||||
$(ROLLBACK_TEST_APEX_V2)
|
||||
LOCAL_MANIFEST_FILE := RollbackTest/AndroidManifest.xml
|
||||
@@ -103,5 +140,9 @@ include $(BUILD_HOST_JAVA_LIBRARY)
|
||||
ROLLBACK_TEST_APP_AV1 :=
|
||||
ROLLBACK_TEST_APP_AV2 :=
|
||||
ROLLBACK_TEST_APP_A_CRASHING_V2 :=
|
||||
ROLLBACK_TEST_APP_A_SPLIT_V1 :=
|
||||
ROLLBACK_TEST_APP_A_SPLIT_V1_SPLIT :=
|
||||
ROLLBACK_TEST_APP_A_SPLIT_V2 :=
|
||||
ROLLBACK_TEST_APP_A_SPLIT_V2_SPLIT :=
|
||||
ROLLBACK_TEST_APP_BV1 :=
|
||||
ROLLBACK_TEST_APP_BV2 :=
|
||||
|
||||
@@ -441,6 +441,39 @@ public class RollbackTest {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Test rollback of apks involving splits.
|
||||
*/
|
||||
@Test
|
||||
public void testRollbackWithSplits() throws Exception {
|
||||
try {
|
||||
RollbackTestUtils.adoptShellPermissionIdentity(
|
||||
Manifest.permission.INSTALL_PACKAGES,
|
||||
Manifest.permission.DELETE_PACKAGES,
|
||||
Manifest.permission.MANAGE_ROLLBACKS);
|
||||
|
||||
RollbackTestUtils.uninstall(TEST_APP_A);
|
||||
RollbackTestUtils.installSplit(false,
|
||||
"RollbackTestAppASplitV1.apk",
|
||||
"RollbackTestAppASplitV1_anydpi.apk");
|
||||
processUserData(TEST_APP_A);
|
||||
|
||||
RollbackTestUtils.installSplit(true,
|
||||
"RollbackTestAppASplitV2.apk",
|
||||
"RollbackTestAppASplitV2_anydpi.apk");
|
||||
processUserData(TEST_APP_A);
|
||||
|
||||
RollbackManager rm = RollbackTestUtils.getRollbackManager();
|
||||
RollbackInfo rollback = getUniqueRollbackInfoForPackage(
|
||||
rm.getAvailableRollbacks(), TEST_APP_A);
|
||||
assertNotNull(rollback);
|
||||
RollbackTestUtils.rollback(rollback.getRollbackId());
|
||||
processUserData(TEST_APP_A);
|
||||
} finally {
|
||||
RollbackTestUtils.dropShellPermissionIdentity();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Test restrictions on rollback broadcast sender.
|
||||
* A random app should not be able to send a ROLLBACK_COMMITTED broadcast.
|
||||
|
||||
@@ -130,6 +130,19 @@ class RollbackTestUtils {
|
||||
*/
|
||||
static void install(String resourceName, boolean enableRollback)
|
||||
throws InterruptedException, IOException {
|
||||
installSplit(enableRollback, resourceName);
|
||||
}
|
||||
|
||||
/**
|
||||
* Installs the apk with the given name and its splits.
|
||||
*
|
||||
* @param enableRollback if rollback should be enabled.
|
||||
* @param resourceNames names of class loader resources for the apk and
|
||||
* its splits to install.
|
||||
* @throws AssertionError if the installation fails.
|
||||
*/
|
||||
static void installSplit(boolean enableRollback, String... resourceNames)
|
||||
throws InterruptedException, IOException {
|
||||
Context context = InstrumentationRegistry.getContext();
|
||||
PackageInstaller.Session session = null;
|
||||
PackageInstaller packageInstaller = context.getPackageManager().getPackageInstaller();
|
||||
@@ -142,12 +155,14 @@ class RollbackTestUtils {
|
||||
session = packageInstaller.openSession(sessionId);
|
||||
|
||||
ClassLoader loader = RollbackTest.class.getClassLoader();
|
||||
try (OutputStream packageInSession = session.openWrite(resourceName, 0, -1);
|
||||
InputStream is = loader.getResourceAsStream(resourceName);) {
|
||||
byte[] buffer = new byte[4096];
|
||||
int n;
|
||||
while ((n = is.read(buffer)) >= 0) {
|
||||
packageInSession.write(buffer, 0, n);
|
||||
for (String resourceName : resourceNames) {
|
||||
try (OutputStream packageInSession = session.openWrite(resourceName, 0, -1);
|
||||
InputStream is = loader.getResourceAsStream(resourceName);) {
|
||||
byte[] buffer = new byte[4096];
|
||||
int n;
|
||||
while ((n = is.read(buffer)) >= 0) {
|
||||
packageInSession.write(buffer, 0, n);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -23,7 +23,6 @@
|
||||
<uses-sdk android:minSdkVersion="19" />
|
||||
|
||||
<application android:label="Rollback Test App A v2">
|
||||
<meta-data android:name="version" android:value="2" />
|
||||
<receiver android:name="com.android.tests.rollback.testapp.ProcessUserData"
|
||||
android:exported="true" />
|
||||
<activity android:name="com.android.tests.rollback.testapp.CrashingMainActivity">
|
||||
|
||||
@@ -23,7 +23,6 @@
|
||||
<uses-sdk android:minSdkVersion="19" />
|
||||
|
||||
<application android:label="Rollback Test App A v1">
|
||||
<meta-data android:name="version" android:value="1" />
|
||||
<receiver android:name="com.android.tests.rollback.testapp.ProcessUserData"
|
||||
android:exported="true" />
|
||||
<activity android:name="com.android.tests.rollback.testapp.MainActivity">
|
||||
|
||||
@@ -23,7 +23,6 @@
|
||||
<uses-sdk android:minSdkVersion="19" />
|
||||
|
||||
<application android:label="Rollback Test App A v2">
|
||||
<meta-data android:name="version" android:value="2" />
|
||||
<receiver android:name="com.android.tests.rollback.testapp.ProcessUserData"
|
||||
android:exported="true" />
|
||||
<activity android:name="com.android.tests.rollback.testapp.MainActivity">
|
||||
|
||||
@@ -23,7 +23,6 @@
|
||||
<uses-sdk android:minSdkVersion="19" />
|
||||
|
||||
<application android:label="Rollback Test App B v1">
|
||||
<meta-data android:name="version" android:value="1" />
|
||||
<receiver android:name="com.android.tests.rollback.testapp.ProcessUserData"
|
||||
android:exported="true" />
|
||||
<activity android:name="com.android.tests.rollback.testapp.MainActivity">
|
||||
|
||||
@@ -23,7 +23,6 @@
|
||||
<uses-sdk android:minSdkVersion="19" />
|
||||
|
||||
<application android:label="Rollback Test App B v2">
|
||||
<meta-data android:name="version" android:value="2" />
|
||||
<receiver android:name="com.android.tests.rollback.testapp.ProcessUserData"
|
||||
android:exported="true" />
|
||||
<activity android:name="com.android.tests.rollback.testapp.MainActivity">
|
||||
|
||||
19
tests/RollbackTest/TestApp/res_v1/values-anydpi/values.xml
Normal file
19
tests/RollbackTest/TestApp/res_v1/values-anydpi/values.xml
Normal file
@@ -0,0 +1,19 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Copyright (C) 2019 The Android Open Source Project
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
-->
|
||||
|
||||
<resources>
|
||||
<integer name="split_version">1</integer>
|
||||
</resources>
|
||||
20
tests/RollbackTest/TestApp/res_v1/values/values.xml
Normal file
20
tests/RollbackTest/TestApp/res_v1/values/values.xml
Normal file
@@ -0,0 +1,20 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Copyright (C) 2019 The Android Open Source Project
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
-->
|
||||
|
||||
<resources>
|
||||
<integer name="app_version">1</integer>
|
||||
<integer name="split_version">0</integer>
|
||||
</resources>
|
||||
19
tests/RollbackTest/TestApp/res_v2/values-anydpi/values.xml
Normal file
19
tests/RollbackTest/TestApp/res_v2/values-anydpi/values.xml
Normal file
@@ -0,0 +1,19 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Copyright (C) 2019 The Android Open Source Project
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
-->
|
||||
|
||||
<resources>
|
||||
<integer name="split_version">2</integer>
|
||||
</resources>
|
||||
20
tests/RollbackTest/TestApp/res_v2/values/values.xml
Normal file
20
tests/RollbackTest/TestApp/res_v2/values/values.xml
Normal file
@@ -0,0 +1,20 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Copyright (C) 2019 The Android Open Source Project
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
-->
|
||||
|
||||
<resources>
|
||||
<integer name="app_version">2</integer>
|
||||
<integer name="split_version">0</integer>
|
||||
</resources>
|
||||
@@ -19,9 +19,7 @@ package com.android.tests.rollback.testapp;
|
||||
import android.content.BroadcastReceiver;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.pm.ApplicationInfo;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.os.Bundle;
|
||||
import android.content.res.Resources;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileNotFoundException;
|
||||
@@ -35,6 +33,8 @@ import java.util.Scanner;
|
||||
*/
|
||||
public class ProcessUserData extends BroadcastReceiver {
|
||||
|
||||
private static final String TAG = "RollbackTestApp";
|
||||
|
||||
/**
|
||||
* Exception thrown in case of issue with user data.
|
||||
*/
|
||||
@@ -66,14 +66,19 @@ public class ProcessUserData extends BroadcastReceiver {
|
||||
* @throws UserDataException in case of problems with app user data.
|
||||
*/
|
||||
public void processUserData(Context context) throws UserDataException {
|
||||
int appVersion = 0;
|
||||
try {
|
||||
ApplicationInfo appInfo = context.getPackageManager().getApplicationInfo(
|
||||
context.getPackageName(), PackageManager.GET_META_DATA);
|
||||
Bundle bundle = appInfo.metaData;
|
||||
appVersion = bundle.getInt("version");
|
||||
} catch (PackageManager.NameNotFoundException e) {
|
||||
throw new UserDataException("Unable to get app version info", e);
|
||||
Resources res = context.getResources();
|
||||
String packageName = context.getPackageName();
|
||||
|
||||
int appVersionId = res.getIdentifier("app_version", "integer", packageName);
|
||||
int appVersion = res.getInteger(appVersionId);
|
||||
|
||||
int splitVersionId = res.getIdentifier("split_version", "integer", packageName);
|
||||
int splitVersion = res.getInteger(splitVersionId);
|
||||
|
||||
// Make sure the app version and split versions are compatible.
|
||||
if (appVersion != splitVersion) {
|
||||
throw new UserDataException("Split version " + splitVersion
|
||||
+ " does not match app version " + appVersion);
|
||||
}
|
||||
|
||||
// Read the version of the app's user data and ensure it is compatible
|
||||
|
||||
Reference in New Issue
Block a user