Merge "updater_sample: add HAL compatibility check"
This commit is contained in:
@@ -84,8 +84,8 @@ which HTTP headers are supported.
|
|||||||
- [x] Add applying streaming update
|
- [x] Add applying streaming update
|
||||||
- [x] Add stop/reset the update
|
- [x] Add stop/reset the update
|
||||||
- [x] Add demo for passing HTTP headers to `UpdateEngine#applyPayload`
|
- [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`
|
- [ ] Add tests for `MainActivity`
|
||||||
- [ ] HAL compatibility check
|
|
||||||
- [ ] Change partition demo
|
- [ ] Change partition demo
|
||||||
- [ ] Verify system partition checksum for package
|
- [ ] Verify system partition checksum for package
|
||||||
- [ ] Add non-A/B updates demo
|
- [ ] Add non-A/B updates demo
|
||||||
|
|||||||
+59
-26
@@ -16,6 +16,7 @@
|
|||||||
|
|
||||||
package com.example.android.systemupdatersample.services;
|
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.OTA_PACKAGE_DIR;
|
||||||
import static com.example.android.systemupdatersample.util.PackageFiles.PAYLOAD_BINARY_FILE_NAME;
|
import static com.example.android.systemupdatersample.util.PackageFiles.PAYLOAD_BINARY_FILE_NAME;
|
||||||
import static com.example.android.systemupdatersample.util.PackageFiles.PAYLOAD_PROPERTIES_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.content.Intent;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.os.Handler;
|
import android.os.Handler;
|
||||||
|
import android.os.RecoverySystem;
|
||||||
import android.os.ResultReceiver;
|
import android.os.ResultReceiver;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
|
|
||||||
@@ -36,7 +38,9 @@ import com.example.android.systemupdatersample.util.PayloadSpecs;
|
|||||||
import com.example.android.systemupdatersample.util.UpdateConfigs;
|
import com.example.android.systemupdatersample.util.UpdateConfigs;
|
||||||
import com.google.common.collect.ImmutableSet;
|
import com.google.common.collect.ImmutableSet;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.nio.file.Files;
|
||||||
import java.nio.file.Paths;
|
import java.nio.file.Paths;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
|
|
||||||
@@ -119,45 +123,51 @@ public class PrepareStreamingService extends IntentService {
|
|||||||
ResultReceiver resultReceiver = intent.getParcelableExtra(EXTRA_PARAM_RESULT_RECEIVER);
|
ResultReceiver resultReceiver = intent.getParcelableExtra(EXTRA_PARAM_RESULT_RECEIVER);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
downloadPreStreamingFiles(config, OTA_PACKAGE_DIR);
|
PayloadSpec spec = execute(config);
|
||||||
} catch (IOException e) {
|
resultReceiver.send(RESULT_CODE_SUCCESS, CallbackResultReceiver.createBundle(spec));
|
||||||
Log.e(TAG, "Failed to download pre-streaming files", e);
|
} catch (Exception e) {
|
||||||
|
Log.e(TAG, "Failed to prepare streaming update", e);
|
||||||
resultReceiver.send(RESULT_CODE_ERROR, null);
|
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 =
|
Optional<UpdateConfig.PackageFile> payloadBinary =
|
||||||
UpdateConfigs.getPropertyFile(PAYLOAD_BINARY_FILE_NAME, config);
|
UpdateConfigs.getPropertyFile(PAYLOAD_BINARY_FILE_NAME, config);
|
||||||
|
|
||||||
if (!payloadBinary.isPresent()) {
|
if (!payloadBinary.isPresent()) {
|
||||||
Log.e(TAG, "Failed to find " + PAYLOAD_BINARY_FILE_NAME + " in config");
|
throw new PreparationFailedException(
|
||||||
resultReceiver.send(RESULT_CODE_ERROR, null);
|
"Failed to find " + PAYLOAD_BINARY_FILE_NAME + " in config");
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Optional<UpdateConfig.PackageFile> properties =
|
if (!UpdateConfigs.getPropertyFile(PAYLOAD_PROPERTIES_FILE_NAME, config).isPresent()
|
||||||
UpdateConfigs.getPropertyFile(PAYLOAD_PROPERTIES_FILE_NAME, config);
|
|| !Paths.get(OTA_PACKAGE_DIR, PAYLOAD_PROPERTIES_FILE_NAME).toFile().exists()) {
|
||||||
|
throw new IOException(PAYLOAD_PROPERTIES_FILE_NAME + " not found");
|
||||||
if (!properties.isPresent()) {
|
|
||||||
Log.e(TAG, "Failed to find " + PAYLOAD_PROPERTIES_FILE_NAME + " in config");
|
|
||||||
resultReceiver.send(RESULT_CODE_ERROR, null);
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
PayloadSpec spec;
|
File compatibilityFile = Paths.get(OTA_PACKAGE_DIR, COMPATIBILITY_ZIP_FILE_NAME).toFile();
|
||||||
try {
|
if (compatibilityFile.isFile()) {
|
||||||
spec = PayloadSpecs.forStreaming(config.getUrl(),
|
Log.i(TAG, "Verifying OTA package for compatibility with the device");
|
||||||
payloadBinary.get().getOffset(),
|
if (!verifyPackageCompatibility(compatibilityFile)) {
|
||||||
payloadBinary.get().getSize(),
|
throw new PreparationFailedException(
|
||||||
Paths.get(OTA_PACKAGE_DIR, properties.get().getFilename()).toFile()
|
"OTA package is not compatible with this device");
|
||||||
);
|
}
|
||||||
} catch (IOException e) {
|
|
||||||
Log.e(TAG, "PayloadSpecs failed to create PayloadSpec for streaming", e);
|
|
||||||
resultReceiver.send(RESULT_CODE_ERROR, null);
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
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)
|
private static void downloadPreStreamingFiles(UpdateConfig config, String dir)
|
||||||
throws IOException {
|
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);
|
Log.d(TAG, "Downloading files to " + dir);
|
||||||
for (UpdateConfig.PackageFile file : config.getStreamingMetadata().getPropertyFiles()) {
|
for (UpdateConfig.PackageFile file : config.getStreamingMetadata().getPropertyFiles()) {
|
||||||
if (PRE_STREAMING_FILES_SET.contains(file.getFilename())) {
|
if (PRE_STREAMING_FILES_SET.contains(file.getFilename())) {
|
||||||
@@ -182,6 +196,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}
|
* Used by {@link PrepareStreamingService} to pass {@link PayloadSpec}
|
||||||
* to {@link UpdateResultCallback#onReceiveResult}.
|
* to {@link UpdateResultCallback#onReceiveResult}.
|
||||||
@@ -213,4 +240,10 @@ public class PrepareStreamingService extends IntentService {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static class PreparationFailedException extends Exception {
|
||||||
|
PreparationFailedException(String message) {
|
||||||
|
super(message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user