From 238beb73739071735a6bcbe462e27ab09a747f02 Mon Sep 17 00:00:00 2001 From: Zhomart Mukhamejanov Date: Wed, 9 May 2018 16:25:40 -0700 Subject: updater_sample: add switch slot demo - Add util/UpdateEngineProperties.java - Set SWITCH_SLOT_ON_REBOOT=0 when update is applied - Allow user to switch slot to the updated partition manually - Add config "ab_config.force_switch_slot" - Add ab_force_switch_slot to tools/gen_update_config.py Test: manually on the marlin device Bug: 79492522 Change-Id: I52f818b576d52a052b5427ba3f732cb2371ddb06 Signed-off-by: Zhomart Mukhamejanov --- .../systemupdatersample/ui/MainActivity.java | 83 ++++++++++++++++++++-- 1 file changed, 76 insertions(+), 7 deletions(-) (limited to 'updater_sample/src/com/example/android/systemupdatersample/ui/MainActivity.java') diff --git a/updater_sample/src/com/example/android/systemupdatersample/ui/MainActivity.java b/updater_sample/src/com/example/android/systemupdatersample/ui/MainActivity.java index 170825635..c5a7f9556 100644 --- a/updater_sample/src/com/example/android/systemupdatersample/ui/MainActivity.java +++ b/updater_sample/src/com/example/android/systemupdatersample/ui/MainActivity.java @@ -18,6 +18,7 @@ package com.example.android.systemupdatersample.ui; import android.app.Activity; import android.app.AlertDialog; +import android.graphics.Color; import android.os.Build; import android.os.Bundle; import android.os.UpdateEngine; @@ -38,11 +39,13 @@ import com.example.android.systemupdatersample.services.PrepareStreamingService; import com.example.android.systemupdatersample.util.PayloadSpecs; import com.example.android.systemupdatersample.util.UpdateConfigs; import com.example.android.systemupdatersample.util.UpdateEngineErrorCodes; +import com.example.android.systemupdatersample.util.UpdateEngineProperties; import com.example.android.systemupdatersample.util.UpdateEngineStatuses; import java.io.IOException; import java.util.ArrayList; import java.util.List; +import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicInteger; /** @@ -66,10 +69,14 @@ public class MainActivity extends Activity { private ProgressBar mProgressBar; private TextView mTextViewStatus; private TextView mTextViewCompletion; + private TextView mTextViewUpdateInfo; + private Button mButtonSwitchSlot; private List mConfigs; private AtomicInteger mUpdateEngineStatus = new AtomicInteger(UpdateEngine.UpdateStatusConstants.IDLE); + private PayloadSpec mLastPayloadSpec; + private AtomicBoolean mManualSwitchSlotRequired = new AtomicBoolean(true); /** * Listen to {@code update_engine} events. @@ -93,6 +100,8 @@ public class MainActivity extends Activity { this.mProgressBar = findViewById(R.id.progressBar); this.mTextViewStatus = findViewById(R.id.textViewStatus); this.mTextViewCompletion = findViewById(R.id.textViewCompletion); + this.mTextViewUpdateInfo = findViewById(R.id.textViewUpdateInfo); + this.mButtonSwitchSlot = findViewById(R.id.buttonSwitchSlot); this.mTextViewConfigsDirHint.setText(UpdateConfigs.getConfigsRoot(this)); @@ -172,6 +181,13 @@ public class MainActivity extends Activity { .setNegativeButton(android.R.string.cancel, null).show(); } + /** + * switch slot button clicked + */ + public void onSwitchSlotClick(View view) { + setSwitchSlotOnReboot(); + } + /** * Invoked when anything changes. The value of {@code status} will * be one of the values from {@link UpdateEngine.UpdateStatusConstants}, @@ -185,16 +201,16 @@ public class MainActivity extends Activity { Log.e("UpdateEngine", "StatusUpdate - status=" + UpdateEngineStatuses.getStatusText(status) + "/" + status); - setUiStatus(status); Toast.makeText(this, "Update Status changed", Toast.LENGTH_LONG) .show(); - if (status != UpdateEngine.UpdateStatusConstants.IDLE) { - Log.d(TAG, "status changed, setting ui to updating mode"); - uiSetUpdating(); - } else { + if (status == UpdateEngine.UpdateStatusConstants.IDLE) { Log.d(TAG, "status changed, resetting ui"); uiReset(); + } else { + Log.d(TAG, "status changed, setting ui to updating mode"); + uiSetUpdating(); } + setUiStatus(status); }); } } @@ -215,6 +231,13 @@ public class MainActivity extends Activity { + " " + state); Toast.makeText(this, "Update completed", Toast.LENGTH_LONG).show(); setUiCompletion(errorCode); + if (errorCode == UpdateEngineErrorCodes.UPDATED_BUT_NOT_ACTIVE) { + // if update was successfully applied. + if (mManualSwitchSlotRequired.get()) { + // Show "Switch Slot" button. + uiShowSwitchSlotInfo(); + } + } }); } @@ -231,6 +254,7 @@ public class MainActivity extends Activity { mProgressBar.setVisibility(ProgressBar.INVISIBLE); mTextViewStatus.setText(R.string.unknown); mTextViewCompletion.setText(R.string.unknown); + uiHideSwitchSlotInfo(); } /** sets ui updating mode */ @@ -245,6 +269,16 @@ public class MainActivity extends Activity { mProgressBar.setVisibility(ProgressBar.VISIBLE); } + private void uiShowSwitchSlotInfo() { + mButtonSwitchSlot.setEnabled(true); + mTextViewUpdateInfo.setTextColor(Color.parseColor("#777777")); + } + + private void uiHideSwitchSlotInfo() { + mTextViewUpdateInfo.setTextColor(Color.parseColor("#AAAAAA")); + mButtonSwitchSlot.setEnabled(false); + } + /** * loads json configurations from configs dir that is defined in {@link UpdateConfigs}. */ @@ -290,6 +324,17 @@ public class MainActivity extends Activity { * Applies the given update */ private void applyUpdate(final UpdateConfig config) { + List extraProperties = new ArrayList<>(); + + if (!config.getAbConfig().getForceSwitchSlot()) { + // Disable switch slot on reboot, which is enabled by default. + // User will enable it manually by clicking "Switch Slot" button on the screen. + extraProperties.add(UpdateEngineProperties.PROPERTY_DISABLE_SWITCH_SLOT_ON_REBOOT); + mManualSwitchSlotRequired.set(true); + } else { + mManualSwitchSlotRequired.set(false); + } + if (config.getInstallType() == UpdateConfig.AB_INSTALL_TYPE_NON_STREAMING) { PayloadSpec payload; try { @@ -300,12 +345,11 @@ public class MainActivity extends Activity { .show(); return; } - updateEngineApplyPayload(payload, null); + updateEngineApplyPayload(payload, extraProperties); } else { Log.d(TAG, "Starting PrepareStreamingService"); PrepareStreamingService.startService(this, config, (code, payloadSpec) -> { if (code == PrepareStreamingService.RESULT_CODE_SUCCESS) { - List extraProperties = new ArrayList<>(); extraProperties.add("USER_AGENT=" + HTTP_USER_AGENT); config.getStreamingMetadata() .getAuthorization() @@ -332,6 +376,8 @@ public class MainActivity extends Activity { * @param extraProperties additional properties to pass to {@link UpdateEngine#applyPayload} */ private void updateEngineApplyPayload(PayloadSpec payloadSpec, List extraProperties) { + mLastPayloadSpec = payloadSpec; + ArrayList properties = new ArrayList<>(payloadSpec.getProperties()); if (extraProperties != null) { properties.addAll(extraProperties); @@ -351,6 +397,29 @@ public class MainActivity extends Activity { } } + /** + * Sets the new slot that has the updated partitions as the active slot, + * which device will boot into next time. + * This method is only supposed to be called after the payload is applied. + * + * Invoking {@link UpdateEngine#applyPayload} with the same payload url, offset, size + * and payload metadata headers doesn't trigger new update. It can be used to just switch + * active A/B slot. + * + * {@link UpdateEngine#applyPayload} might take several seconds to finish, and it will + * invoke callbacks {@link this#onStatusUpdate} and {@link this#onPayloadApplicationComplete)}. + */ + private void setSwitchSlotOnReboot() { + Log.d(TAG, "setSwitchSlotOnReboot invoked"); + List extraProperties = new ArrayList<>(); + // PROPERTY_SKIP_POST_INSTALL should be passed on to skip post-installation hooks. + extraProperties.add(UpdateEngineProperties.PROPERTY_SKIP_POST_INSTALL); + // It sets property SWITCH_SLOT_ON_REBOOT=1 by default. + // HTTP headers are not required, UpdateEngine is not expected to stream payload. + updateEngineApplyPayload(mLastPayloadSpec, extraProperties); + uiHideSwitchSlotInfo(); + } + /** * Requests update engine to stop any ongoing update. If an update has been applied, * leave it as is. -- cgit v1.2.3