Loading updater_sample/README.md +1 −1 Original line number Diff line number Diff line Loading @@ -220,7 +220,7 @@ privileged system app, so it's granted the required permissions to access - [x] Add Sample app update state (separate from update_engine status) - [x] Add smart update completion detection using onStatusUpdate - [x] Add pause/resume demo - [ ] Verify system partition checksum for package - [x] Verify system partition checksum for package ## Running tests Loading updater_sample/src/com/example/android/systemupdatersample/UpdateConfig.java +52 −60 Original line number Diff line number Diff line Loading @@ -25,6 +25,7 @@ import org.json.JSONObject; import java.io.File; import java.io.Serializable; import java.util.ArrayList; import java.util.Optional; /** Loading Loading @@ -67,31 +68,28 @@ public class UpdateConfig implements Parcelable { throw new JSONException("Invalid type, expected either " + "NON_STREAMING or STREAMING, got " + o.getString("ab_install_type")); } if (c.mAbInstallType == AB_INSTALL_TYPE_STREAMING) { JSONObject meta = o.getJSONObject("ab_streaming_metadata"); JSONArray propertyFilesJson = meta.getJSONArray("property_files"); PackageFile[] propertyFiles = new PackageFile[propertyFilesJson.length()]; // TODO: parse only for A/B updates when non-A/B is implemented JSONObject ab = o.getJSONObject("ab_config"); boolean forceSwitchSlot = ab.getBoolean("force_switch_slot"); boolean verifyPayloadMetadata = ab.getBoolean("verify_payload_metadata"); ArrayList<PackageFile> propertyFiles = new ArrayList<>(); if (ab.has("property_files")) { JSONArray propertyFilesJson = ab.getJSONArray("property_files"); for (int i = 0; i < propertyFilesJson.length(); i++) { JSONObject p = propertyFilesJson.getJSONObject(i); propertyFiles[i] = new PackageFile( propertyFiles.add(new PackageFile( p.getString("filename"), p.getLong("offset"), p.getLong("size")); p.getLong("size"))); } String authorization = null; if (meta.has("authorization")) { authorization = meta.getString("authorization"); } c.mAbStreamingMetadata = new StreamingMetadata( propertyFiles, String authorization = ab.optString("authorization", null); c.mAbConfig = new AbConfig( forceSwitchSlot, verifyPayloadMetadata, propertyFiles.toArray(new PackageFile[0]), authorization); } // TODO: parse only for A/B updates when non-A/B is implemented JSONObject ab = o.getJSONObject("ab_config"); boolean forceSwitchSlot = ab.getBoolean("force_switch_slot"); c.mAbConfig = new AbConfig(forceSwitchSlot); c.mRawJson = json; return c; Loading @@ -112,9 +110,6 @@ public class UpdateConfig implements Parcelable { /** non-streaming (first saves locally) OR streaming (on the fly) */ private int mAbInstallType; /** metadata is required only for streaming update */ private StreamingMetadata mAbStreamingMetadata; /** A/B update configurations */ private AbConfig mAbConfig; Loading @@ -127,7 +122,6 @@ public class UpdateConfig implements Parcelable { this.mName = in.readString(); this.mUrl = in.readString(); this.mAbInstallType = in.readInt(); this.mAbStreamingMetadata = (StreamingMetadata) in.readSerializable(); this.mAbConfig = (AbConfig) in.readSerializable(); this.mRawJson = in.readString(); } Loading @@ -154,10 +148,6 @@ public class UpdateConfig implements Parcelable { return mAbInstallType; } public StreamingMetadata getStreamingMetadata() { return mAbStreamingMetadata; } public AbConfig getAbConfig() { return mAbConfig; } Loading Loading @@ -185,42 +175,10 @@ public class UpdateConfig implements Parcelable { dest.writeString(mName); dest.writeString(mUrl); dest.writeInt(mAbInstallType); dest.writeSerializable(mAbStreamingMetadata); dest.writeSerializable(mAbConfig); dest.writeString(mRawJson); } /** * Metadata for streaming A/B update. */ public static class StreamingMetadata implements Serializable { private static final long serialVersionUID = 31042L; /** defines beginning of update data in archive */ private PackageFile[] mPropertyFiles; /** * SystemUpdaterSample receives the authorization token from the OTA server, in addition * to the package URL. It passes on the info to update_engine, so that the latter can * fetch the data from the package server directly with the token. */ private String mAuthorization; public StreamingMetadata(PackageFile[] propertyFiles, String authorization) { this.mPropertyFiles = propertyFiles; this.mAuthorization = authorization; } public PackageFile[] getPropertyFiles() { return mPropertyFiles; } public Optional<String> getAuthorization() { return mAuthorization == null ? Optional.empty() : Optional.of(mAuthorization); } } /** * Description of a file in an OTA package zip file. */ Loading Loading @@ -269,14 +227,48 @@ public class UpdateConfig implements Parcelable { */ private boolean mForceSwitchSlot; public AbConfig(boolean forceSwitchSlot) { /** * if set true device will boot to new slot, otherwise user manually * switches slot on the screen. */ private boolean mVerifyPayloadMetadata; /** defines beginning of update data in archive */ private PackageFile[] mPropertyFiles; /** * SystemUpdaterSample receives the authorization token from the OTA server, in addition * to the package URL. It passes on the info to update_engine, so that the latter can * fetch the data from the package server directly with the token. */ private String mAuthorization; public AbConfig( boolean forceSwitchSlot, boolean verifyPayloadMetadata, PackageFile[] propertyFiles, String authorization) { this.mForceSwitchSlot = forceSwitchSlot; this.mVerifyPayloadMetadata = verifyPayloadMetadata; this.mPropertyFiles = propertyFiles; this.mAuthorization = authorization; } public boolean getForceSwitchSlot() { return mForceSwitchSlot; } public boolean getVerifyPayloadMetadata() { return mVerifyPayloadMetadata; } public PackageFile[] getPropertyFiles() { return mPropertyFiles; } public Optional<String> getAuthorization() { return mAuthorization == null ? Optional.empty() : Optional.of(mAuthorization); } } } updater_sample/src/com/example/android/systemupdatersample/UpdateManager.java +1 −1 Original line number Diff line number Diff line Loading @@ -324,7 +324,7 @@ public class UpdateManager { if (code == PrepareStreamingService.RESULT_CODE_SUCCESS) { builder.setPayload(payloadSpec); builder.addExtraProperty("USER_AGENT=" + HTTP_USER_AGENT); config.getStreamingMetadata() config.getAbConfig() .getAuthorization() .ifPresent(s -> builder.addExtraProperty("AUTHORIZATION=" + s)); updateEngineApplyPayload(builder.build()); Loading updater_sample/src/com/example/android/systemupdatersample/services/PrepareStreamingService.java +2 −2 Original line number Diff line number Diff line Loading @@ -173,7 +173,7 @@ public class PrepareStreamingService extends IntentService { } /** * Downloads files defined in {@link UpdateConfig#getStreamingMetadata()} * Downloads files defined in {@link UpdateConfig#getAbConfig()} * and exists in {@code PRE_STREAMING_FILES_SET}, and put them * in directory {@code dir}. * @throws IOException when can't download a file Loading @@ -185,7 +185,7 @@ public class PrepareStreamingService extends IntentService { Files.deleteIfExists(Paths.get(OTA_PACKAGE_DIR, file)); } Log.d(TAG, "Downloading files to " + dir); for (UpdateConfig.PackageFile file : config.getStreamingMetadata().getPropertyFiles()) { for (UpdateConfig.PackageFile file : config.getAbConfig().getPropertyFiles()) { if (PRE_STREAMING_FILES_SET.contains(file.getFilename())) { Log.d(TAG, "Downloading file " + file.getFilename()); FileDownloader downloader = new FileDownloader( Loading updater_sample/src/com/example/android/systemupdatersample/util/UpdateConfigs.java +2 −2 Original line number Diff line number Diff line Loading @@ -83,7 +83,7 @@ public final class UpdateConfigs { /** * @param filename searches by given filename * @param config searches in {@link UpdateConfig#getStreamingMetadata()} * @param config searches in {@link UpdateConfig#getAbConfig()} * @return offset and size of {@code filename} in the package zip file * stored as {@link UpdateConfig.PackageFile}. */ Loading @@ -91,7 +91,7 @@ public final class UpdateConfigs { final String filename, UpdateConfig config) { return Arrays .stream(config.getStreamingMetadata().getPropertyFiles()) .stream(config.getAbConfig().getPropertyFiles()) .filter(file -> filename.equals(file.getFilename())) .findFirst(); } Loading Loading
updater_sample/README.md +1 −1 Original line number Diff line number Diff line Loading @@ -220,7 +220,7 @@ privileged system app, so it's granted the required permissions to access - [x] Add Sample app update state (separate from update_engine status) - [x] Add smart update completion detection using onStatusUpdate - [x] Add pause/resume demo - [ ] Verify system partition checksum for package - [x] Verify system partition checksum for package ## Running tests Loading
updater_sample/src/com/example/android/systemupdatersample/UpdateConfig.java +52 −60 Original line number Diff line number Diff line Loading @@ -25,6 +25,7 @@ import org.json.JSONObject; import java.io.File; import java.io.Serializable; import java.util.ArrayList; import java.util.Optional; /** Loading Loading @@ -67,31 +68,28 @@ public class UpdateConfig implements Parcelable { throw new JSONException("Invalid type, expected either " + "NON_STREAMING or STREAMING, got " + o.getString("ab_install_type")); } if (c.mAbInstallType == AB_INSTALL_TYPE_STREAMING) { JSONObject meta = o.getJSONObject("ab_streaming_metadata"); JSONArray propertyFilesJson = meta.getJSONArray("property_files"); PackageFile[] propertyFiles = new PackageFile[propertyFilesJson.length()]; // TODO: parse only for A/B updates when non-A/B is implemented JSONObject ab = o.getJSONObject("ab_config"); boolean forceSwitchSlot = ab.getBoolean("force_switch_slot"); boolean verifyPayloadMetadata = ab.getBoolean("verify_payload_metadata"); ArrayList<PackageFile> propertyFiles = new ArrayList<>(); if (ab.has("property_files")) { JSONArray propertyFilesJson = ab.getJSONArray("property_files"); for (int i = 0; i < propertyFilesJson.length(); i++) { JSONObject p = propertyFilesJson.getJSONObject(i); propertyFiles[i] = new PackageFile( propertyFiles.add(new PackageFile( p.getString("filename"), p.getLong("offset"), p.getLong("size")); p.getLong("size"))); } String authorization = null; if (meta.has("authorization")) { authorization = meta.getString("authorization"); } c.mAbStreamingMetadata = new StreamingMetadata( propertyFiles, String authorization = ab.optString("authorization", null); c.mAbConfig = new AbConfig( forceSwitchSlot, verifyPayloadMetadata, propertyFiles.toArray(new PackageFile[0]), authorization); } // TODO: parse only for A/B updates when non-A/B is implemented JSONObject ab = o.getJSONObject("ab_config"); boolean forceSwitchSlot = ab.getBoolean("force_switch_slot"); c.mAbConfig = new AbConfig(forceSwitchSlot); c.mRawJson = json; return c; Loading @@ -112,9 +110,6 @@ public class UpdateConfig implements Parcelable { /** non-streaming (first saves locally) OR streaming (on the fly) */ private int mAbInstallType; /** metadata is required only for streaming update */ private StreamingMetadata mAbStreamingMetadata; /** A/B update configurations */ private AbConfig mAbConfig; Loading @@ -127,7 +122,6 @@ public class UpdateConfig implements Parcelable { this.mName = in.readString(); this.mUrl = in.readString(); this.mAbInstallType = in.readInt(); this.mAbStreamingMetadata = (StreamingMetadata) in.readSerializable(); this.mAbConfig = (AbConfig) in.readSerializable(); this.mRawJson = in.readString(); } Loading @@ -154,10 +148,6 @@ public class UpdateConfig implements Parcelable { return mAbInstallType; } public StreamingMetadata getStreamingMetadata() { return mAbStreamingMetadata; } public AbConfig getAbConfig() { return mAbConfig; } Loading Loading @@ -185,42 +175,10 @@ public class UpdateConfig implements Parcelable { dest.writeString(mName); dest.writeString(mUrl); dest.writeInt(mAbInstallType); dest.writeSerializable(mAbStreamingMetadata); dest.writeSerializable(mAbConfig); dest.writeString(mRawJson); } /** * Metadata for streaming A/B update. */ public static class StreamingMetadata implements Serializable { private static final long serialVersionUID = 31042L; /** defines beginning of update data in archive */ private PackageFile[] mPropertyFiles; /** * SystemUpdaterSample receives the authorization token from the OTA server, in addition * to the package URL. It passes on the info to update_engine, so that the latter can * fetch the data from the package server directly with the token. */ private String mAuthorization; public StreamingMetadata(PackageFile[] propertyFiles, String authorization) { this.mPropertyFiles = propertyFiles; this.mAuthorization = authorization; } public PackageFile[] getPropertyFiles() { return mPropertyFiles; } public Optional<String> getAuthorization() { return mAuthorization == null ? Optional.empty() : Optional.of(mAuthorization); } } /** * Description of a file in an OTA package zip file. */ Loading Loading @@ -269,14 +227,48 @@ public class UpdateConfig implements Parcelable { */ private boolean mForceSwitchSlot; public AbConfig(boolean forceSwitchSlot) { /** * if set true device will boot to new slot, otherwise user manually * switches slot on the screen. */ private boolean mVerifyPayloadMetadata; /** defines beginning of update data in archive */ private PackageFile[] mPropertyFiles; /** * SystemUpdaterSample receives the authorization token from the OTA server, in addition * to the package URL. It passes on the info to update_engine, so that the latter can * fetch the data from the package server directly with the token. */ private String mAuthorization; public AbConfig( boolean forceSwitchSlot, boolean verifyPayloadMetadata, PackageFile[] propertyFiles, String authorization) { this.mForceSwitchSlot = forceSwitchSlot; this.mVerifyPayloadMetadata = verifyPayloadMetadata; this.mPropertyFiles = propertyFiles; this.mAuthorization = authorization; } public boolean getForceSwitchSlot() { return mForceSwitchSlot; } public boolean getVerifyPayloadMetadata() { return mVerifyPayloadMetadata; } public PackageFile[] getPropertyFiles() { return mPropertyFiles; } public Optional<String> getAuthorization() { return mAuthorization == null ? Optional.empty() : Optional.of(mAuthorization); } } }
updater_sample/src/com/example/android/systemupdatersample/UpdateManager.java +1 −1 Original line number Diff line number Diff line Loading @@ -324,7 +324,7 @@ public class UpdateManager { if (code == PrepareStreamingService.RESULT_CODE_SUCCESS) { builder.setPayload(payloadSpec); builder.addExtraProperty("USER_AGENT=" + HTTP_USER_AGENT); config.getStreamingMetadata() config.getAbConfig() .getAuthorization() .ifPresent(s -> builder.addExtraProperty("AUTHORIZATION=" + s)); updateEngineApplyPayload(builder.build()); Loading
updater_sample/src/com/example/android/systemupdatersample/services/PrepareStreamingService.java +2 −2 Original line number Diff line number Diff line Loading @@ -173,7 +173,7 @@ public class PrepareStreamingService extends IntentService { } /** * Downloads files defined in {@link UpdateConfig#getStreamingMetadata()} * Downloads files defined in {@link UpdateConfig#getAbConfig()} * and exists in {@code PRE_STREAMING_FILES_SET}, and put them * in directory {@code dir}. * @throws IOException when can't download a file Loading @@ -185,7 +185,7 @@ public class PrepareStreamingService extends IntentService { Files.deleteIfExists(Paths.get(OTA_PACKAGE_DIR, file)); } Log.d(TAG, "Downloading files to " + dir); for (UpdateConfig.PackageFile file : config.getStreamingMetadata().getPropertyFiles()) { for (UpdateConfig.PackageFile file : config.getAbConfig().getPropertyFiles()) { if (PRE_STREAMING_FILES_SET.contains(file.getFilename())) { Log.d(TAG, "Downloading file " + file.getFilename()); FileDownloader downloader = new FileDownloader( Loading
updater_sample/src/com/example/android/systemupdatersample/util/UpdateConfigs.java +2 −2 Original line number Diff line number Diff line Loading @@ -83,7 +83,7 @@ public final class UpdateConfigs { /** * @param filename searches by given filename * @param config searches in {@link UpdateConfig#getStreamingMetadata()} * @param config searches in {@link UpdateConfig#getAbConfig()} * @return offset and size of {@code filename} in the package zip file * stored as {@link UpdateConfig.PackageFile}. */ Loading @@ -91,7 +91,7 @@ public final class UpdateConfigs { final String filename, UpdateConfig config) { return Arrays .stream(config.getStreamingMetadata().getPropertyFiles()) .stream(config.getAbConfig().getPropertyFiles()) .filter(file -> filename.equals(file.getFilename())) .findFirst(); } Loading