summaryrefslogtreecommitdiffstats
path: root/updater_sample
diff options
context:
space:
mode:
authorZhomart Mukhamejanov <zhomart@google.com>2018-05-09 18:53:45 +0200
committerZhomart Mukhamejanov <zhomart@google.com>2018-05-10 23:45:52 +0200
commit46a51ac4b651518e7160d83c8462ab7a556bd344 (patch)
treefa2259c2adbed63365e17009a52b679f7f5408f6 /updater_sample
parentMerge "updater_sample: fix UpdateConfig" (diff)
downloadandroid_bootable_recovery-46a51ac4b651518e7160d83c8462ab7a556bd344.tar
android_bootable_recovery-46a51ac4b651518e7160d83c8462ab7a556bd344.tar.gz
android_bootable_recovery-46a51ac4b651518e7160d83c8462ab7a556bd344.tar.bz2
android_bootable_recovery-46a51ac4b651518e7160d83c8462ab7a556bd344.tar.lz
android_bootable_recovery-46a51ac4b651518e7160d83c8462ab7a556bd344.tar.xz
android_bootable_recovery-46a51ac4b651518e7160d83c8462ab7a556bd344.tar.zst
android_bootable_recovery-46a51ac4b651518e7160d83c8462ab7a556bd344.zip
Diffstat (limited to 'updater_sample')
-rw-r--r--updater_sample/README.md2
-rw-r--r--updater_sample/src/com/example/android/systemupdatersample/services/PrepareStreamingService.java85
2 files changed, 60 insertions, 27 deletions
diff --git a/updater_sample/README.md b/updater_sample/README.md
index 7e25b070c..95e57dbe9 100644
--- a/updater_sample/README.md
+++ b/updater_sample/README.md
@@ -84,8 +84,8 @@ which HTTP headers are supported.
- [x] Add applying streaming update
- [x] Add stop/reset the update
- [x] Add demo for passing HTTP headers to `UpdateEngine#applyPayload`
+- [x] [Package compatibility check](https://source.android.com/devices/architecture/vintf/match-rules)
- [ ] Add tests for `MainActivity`
-- [ ] HAL compatibility check
- [ ] Change partition demo
- [ ] Verify system partition checksum for package
- [ ] Add non-A/B updates demo
diff --git a/updater_sample/src/com/example/android/systemupdatersample/services/PrepareStreamingService.java b/updater_sample/src/com/example/android/systemupdatersample/services/PrepareStreamingService.java
index 840a6d607..222bb0a58 100644
--- a/updater_sample/src/com/example/android/systemupdatersample/services/PrepareStreamingService.java
+++ b/updater_sample/src/com/example/android/systemupdatersample/services/PrepareStreamingService.java
@@ -16,6 +16,7 @@
package com.example.android.systemupdatersample.services;
+import static com.example.android.systemupdatersample.util.PackageFiles.COMPATIBILITY_ZIP_FILE_NAME;
import static com.example.android.systemupdatersample.util.PackageFiles.OTA_PACKAGE_DIR;
import static com.example.android.systemupdatersample.util.PackageFiles.PAYLOAD_BINARY_FILE_NAME;
import static com.example.android.systemupdatersample.util.PackageFiles.PAYLOAD_PROPERTIES_FILE_NAME;
@@ -25,6 +26,7 @@ import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.os.Handler;
+import android.os.RecoverySystem;
import android.os.ResultReceiver;
import android.util.Log;
@@ -36,7 +38,9 @@ import com.example.android.systemupdatersample.util.PayloadSpecs;
import com.example.android.systemupdatersample.util.UpdateConfigs;
import com.google.common.collect.ImmutableSet;
+import java.io.File;
import java.io.IOException;
+import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.Optional;
@@ -119,45 +123,51 @@ public class PrepareStreamingService extends IntentService {
ResultReceiver resultReceiver = intent.getParcelableExtra(EXTRA_PARAM_RESULT_RECEIVER);
try {
- downloadPreStreamingFiles(config, OTA_PACKAGE_DIR);
- } catch (IOException e) {
- Log.e(TAG, "Failed to download pre-streaming files", e);
+ PayloadSpec spec = execute(config);
+ resultReceiver.send(RESULT_CODE_SUCCESS, CallbackResultReceiver.createBundle(spec));
+ } catch (Exception e) {
+ Log.e(TAG, "Failed to prepare streaming update", e);
resultReceiver.send(RESULT_CODE_ERROR, null);
- return;
}
+ }
+
+ /**
+ * 1. Downloads files for streaming updates.
+ * 2. Makes sure required files are present.
+ * 3. Checks OTA package compatibility with the device.
+ * 4. Constructs {@link PayloadSpec} for streaming update.
+ */
+ private static PayloadSpec execute(UpdateConfig config)
+ throws IOException, PreparationFailedException {
+
+ downloadPreStreamingFiles(config, OTA_PACKAGE_DIR);
Optional<UpdateConfig.PackageFile> payloadBinary =
UpdateConfigs.getPropertyFile(PAYLOAD_BINARY_FILE_NAME, config);
if (!payloadBinary.isPresent()) {
- Log.e(TAG, "Failed to find " + PAYLOAD_BINARY_FILE_NAME + " in config");
- resultReceiver.send(RESULT_CODE_ERROR, null);
- return;
+ throw new PreparationFailedException(
+ "Failed to find " + PAYLOAD_BINARY_FILE_NAME + " in config");
}
- Optional<UpdateConfig.PackageFile> properties =
- UpdateConfigs.getPropertyFile(PAYLOAD_PROPERTIES_FILE_NAME, config);
-
- if (!properties.isPresent()) {
- Log.e(TAG, "Failed to find " + PAYLOAD_PROPERTIES_FILE_NAME + " in config");
- resultReceiver.send(RESULT_CODE_ERROR, null);
- return;
+ if (!UpdateConfigs.getPropertyFile(PAYLOAD_PROPERTIES_FILE_NAME, config).isPresent()
+ || !Paths.get(OTA_PACKAGE_DIR, PAYLOAD_PROPERTIES_FILE_NAME).toFile().exists()) {
+ throw new IOException(PAYLOAD_PROPERTIES_FILE_NAME + " not found");
}
- PayloadSpec spec;
- try {
- spec = PayloadSpecs.forStreaming(config.getUrl(),
- payloadBinary.get().getOffset(),
- payloadBinary.get().getSize(),
- Paths.get(OTA_PACKAGE_DIR, properties.get().getFilename()).toFile()
- );
- } catch (IOException e) {
- Log.e(TAG, "PayloadSpecs failed to create PayloadSpec for streaming", e);
- resultReceiver.send(RESULT_CODE_ERROR, null);
- return;
+ File compatibilityFile = Paths.get(OTA_PACKAGE_DIR, COMPATIBILITY_ZIP_FILE_NAME).toFile();
+ if (compatibilityFile.isFile()) {
+ Log.i(TAG, "Verifying OTA package for compatibility with the device");
+ if (!verifyPackageCompatibility(compatibilityFile)) {
+ throw new PreparationFailedException(
+ "OTA package is not compatible with this device");
+ }
}
- resultReceiver.send(RESULT_CODE_SUCCESS, CallbackResultReceiver.createBundle(spec));
+ return PayloadSpecs.forStreaming(config.getUrl(),
+ payloadBinary.get().getOffset(),
+ payloadBinary.get().getSize(),
+ Paths.get(OTA_PACKAGE_DIR, PAYLOAD_PROPERTIES_FILE_NAME).toFile());
}
/**
@@ -168,6 +178,10 @@ public class PrepareStreamingService extends IntentService {
*/
private static void downloadPreStreamingFiles(UpdateConfig config, String dir)
throws IOException {
+ Log.d(TAG, "Deleting existing files from " + dir);
+ for (String file : PRE_STREAMING_FILES_SET) {
+ Files.deleteIfExists(Paths.get(OTA_PACKAGE_DIR, file));
+ }
Log.d(TAG, "Downloading files to " + dir);
for (UpdateConfig.PackageFile file : config.getStreamingMetadata().getPropertyFiles()) {
if (PRE_STREAMING_FILES_SET.contains(file.getFilename())) {
@@ -183,6 +197,19 @@ public class PrepareStreamingService extends IntentService {
}
/**
+ * @param file physical location of {@link PackageFiles#COMPATIBILITY_ZIP_FILE_NAME}
+ * @return true if OTA package is compatible with this device
+ */
+ private static boolean verifyPackageCompatibility(File file) {
+ try {
+ return RecoverySystem.verifyPackageCompatibility(file);
+ } catch (IOException e) {
+ Log.e(TAG, "Failed to verify package compatibility", e);
+ return false;
+ }
+ }
+
+ /**
* Used by {@link PrepareStreamingService} to pass {@link PayloadSpec}
* to {@link UpdateResultCallback#onReceiveResult}.
*/
@@ -213,4 +240,10 @@ public class PrepareStreamingService extends IntentService {
}
}
+ private static class PreparationFailedException extends Exception {
+ PreparationFailedException(String message) {
+ super(message);
+ }
+ }
+
}