Merge "updater_sample: add UpdateData"
am: 8f15a82229
Change-Id: I0b155b9b49e7686170cc51adf6bd84d54e0bc0f1
This commit is contained in:
@@ -26,10 +26,13 @@ import com.example.android.systemupdatersample.util.PayloadSpecs;
|
|||||||
import com.example.android.systemupdatersample.util.UpdateEngineErrorCodes;
|
import com.example.android.systemupdatersample.util.UpdateEngineErrorCodes;
|
||||||
import com.example.android.systemupdatersample.util.UpdateEngineProperties;
|
import com.example.android.systemupdatersample.util.UpdateEngineProperties;
|
||||||
import com.example.android.systemupdatersample.util.UpdaterStates;
|
import com.example.android.systemupdatersample.util.UpdaterStates;
|
||||||
|
import com.google.common.base.Preconditions;
|
||||||
|
import com.google.common.collect.ImmutableList;
|
||||||
import com.google.common.util.concurrent.AtomicDouble;
|
import com.google.common.util.concurrent.AtomicDouble;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
import java.util.concurrent.atomic.AtomicBoolean;
|
import java.util.concurrent.atomic.AtomicBoolean;
|
||||||
@@ -56,15 +59,12 @@ public class UpdateManager {
|
|||||||
new AtomicInteger(UpdateEngine.UpdateStatusConstants.IDLE);
|
new AtomicInteger(UpdateEngine.UpdateStatusConstants.IDLE);
|
||||||
private AtomicInteger mEngineErrorCode = new AtomicInteger(UpdateEngineErrorCodes.UNKNOWN);
|
private AtomicInteger mEngineErrorCode = new AtomicInteger(UpdateEngineErrorCodes.UNKNOWN);
|
||||||
private AtomicDouble mProgress = new AtomicDouble(0);
|
private AtomicDouble mProgress = new AtomicDouble(0);
|
||||||
|
|
||||||
private AtomicInteger mState = new AtomicInteger(UpdaterStates.IDLE);
|
private AtomicInteger mState = new AtomicInteger(UpdaterStates.IDLE);
|
||||||
|
|
||||||
private final UpdateManager.UpdateEngineCallbackImpl
|
|
||||||
mUpdateEngineCallback = new UpdateManager.UpdateEngineCallbackImpl();
|
|
||||||
|
|
||||||
private PayloadSpec mLastPayloadSpec;
|
|
||||||
private AtomicBoolean mManualSwitchSlotRequired = new AtomicBoolean(true);
|
private AtomicBoolean mManualSwitchSlotRequired = new AtomicBoolean(true);
|
||||||
|
|
||||||
|
private UpdateData mLastUpdateData = null;
|
||||||
|
|
||||||
private IntConsumer mOnStateChangeCallback = null;
|
private IntConsumer mOnStateChangeCallback = null;
|
||||||
private IntConsumer mOnEngineStatusUpdateCallback = null;
|
private IntConsumer mOnEngineStatusUpdateCallback = null;
|
||||||
private DoubleConsumer mOnProgressUpdateCallback = null;
|
private DoubleConsumer mOnProgressUpdateCallback = null;
|
||||||
@@ -72,6 +72,9 @@ public class UpdateManager {
|
|||||||
|
|
||||||
private final Object mLock = new Object();
|
private final Object mLock = new Object();
|
||||||
|
|
||||||
|
private final UpdateManager.UpdateEngineCallbackImpl
|
||||||
|
mUpdateEngineCallback = new UpdateManager.UpdateEngineCallbackImpl();
|
||||||
|
|
||||||
public UpdateManager(UpdateEngine updateEngine, PayloadSpecs payloadSpecs) {
|
public UpdateManager(UpdateEngine updateEngine, PayloadSpecs payloadSpecs) {
|
||||||
this.mUpdateEngine = updateEngine;
|
this.mUpdateEngine = updateEngine;
|
||||||
this.mPayloadSpecs = payloadSpecs;
|
this.mPayloadSpecs = payloadSpecs;
|
||||||
@@ -240,6 +243,11 @@ public class UpdateManager {
|
|||||||
mEngineErrorCode.set(UpdateEngineErrorCodes.UNKNOWN);
|
mEngineErrorCode.set(UpdateEngineErrorCodes.UNKNOWN);
|
||||||
setUpdaterState(UpdaterStates.RUNNING);
|
setUpdaterState(UpdaterStates.RUNNING);
|
||||||
|
|
||||||
|
synchronized (mLock) {
|
||||||
|
// Cleaning up previous update data.
|
||||||
|
mLastUpdateData = null;
|
||||||
|
}
|
||||||
|
|
||||||
if (!config.getAbConfig().getForceSwitchSlot()) {
|
if (!config.getAbConfig().getForceSwitchSlot()) {
|
||||||
mManualSwitchSlotRequired.set(true);
|
mManualSwitchSlotRequired.set(true);
|
||||||
} else {
|
} else {
|
||||||
@@ -254,30 +262,32 @@ public class UpdateManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void applyAbNonStreamingUpdate(UpdateConfig config) {
|
private void applyAbNonStreamingUpdate(UpdateConfig config) {
|
||||||
List<String> extraProperties = prepareExtraProperties(config);
|
UpdateData.Builder builder = UpdateData.builder()
|
||||||
|
.setExtraProperties(prepareExtraProperties(config));
|
||||||
|
|
||||||
PayloadSpec payload;
|
|
||||||
try {
|
try {
|
||||||
payload = mPayloadSpecs.forNonStreaming(config.getUpdatePackageFile());
|
builder.setPayload(mPayloadSpecs.forNonStreaming(config.getUpdatePackageFile()));
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
Log.e(TAG, "Error creating payload spec", e);
|
Log.e(TAG, "Error creating payload spec", e);
|
||||||
setUpdaterState(UpdaterStates.ERROR);
|
setUpdaterState(UpdaterStates.ERROR);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
updateEngineApplyPayload(payload, extraProperties);
|
updateEngineApplyPayload(builder.build());
|
||||||
}
|
}
|
||||||
|
|
||||||
private void applyAbStreamingUpdate(Context context, UpdateConfig config) {
|
private void applyAbStreamingUpdate(Context context, UpdateConfig config) {
|
||||||
List<String> extraProperties = prepareExtraProperties(config);
|
UpdateData.Builder builder = UpdateData.builder()
|
||||||
|
.setExtraProperties(prepareExtraProperties(config));
|
||||||
|
|
||||||
Log.d(TAG, "Starting PrepareStreamingService");
|
Log.d(TAG, "Starting PrepareStreamingService");
|
||||||
PrepareStreamingService.startService(context, config, (code, payloadSpec) -> {
|
PrepareStreamingService.startService(context, config, (code, payloadSpec) -> {
|
||||||
if (code == PrepareStreamingService.RESULT_CODE_SUCCESS) {
|
if (code == PrepareStreamingService.RESULT_CODE_SUCCESS) {
|
||||||
extraProperties.add("USER_AGENT=" + HTTP_USER_AGENT);
|
builder.setPayload(payloadSpec);
|
||||||
|
builder.addExtraProperty("USER_AGENT=" + HTTP_USER_AGENT);
|
||||||
config.getStreamingMetadata()
|
config.getStreamingMetadata()
|
||||||
.getAuthorization()
|
.getAuthorization()
|
||||||
.ifPresent(s -> extraProperties.add("AUTHORIZATION=" + s));
|
.ifPresent(s -> builder.addExtraProperty("AUTHORIZATION=" + s));
|
||||||
updateEngineApplyPayload(payloadSpec, extraProperties);
|
updateEngineApplyPayload(builder.build());
|
||||||
} else {
|
} else {
|
||||||
Log.e(TAG, "PrepareStreamingService failed, result code is " + code);
|
Log.e(TAG, "PrepareStreamingService failed, result code is " + code);
|
||||||
setUpdaterState(UpdaterStates.ERROR);
|
setUpdaterState(UpdaterStates.ERROR);
|
||||||
@@ -305,22 +315,20 @@ public class UpdateManager {
|
|||||||
* <p>It's possible that the update engine throws a generic error, such as upon seeing invalid
|
* <p>It's possible that the update engine throws a generic error, such as upon seeing invalid
|
||||||
* payload properties (which come from OTA packages), or failing to set up the network
|
* payload properties (which come from OTA packages), or failing to set up the network
|
||||||
* with the given id.</p>
|
* with the given id.</p>
|
||||||
*
|
|
||||||
* @param payloadSpec contains url, offset and size to {@code PAYLOAD_BINARY_FILE_NAME}
|
|
||||||
* @param extraProperties additional properties to pass to {@link UpdateEngine#applyPayload}
|
|
||||||
*/
|
*/
|
||||||
private void updateEngineApplyPayload(PayloadSpec payloadSpec, List<String> extraProperties) {
|
private void updateEngineApplyPayload(UpdateData update) {
|
||||||
mLastPayloadSpec = payloadSpec;
|
synchronized (mLock) {
|
||||||
|
mLastUpdateData = update;
|
||||||
ArrayList<String> properties = new ArrayList<>(payloadSpec.getProperties());
|
|
||||||
if (extraProperties != null) {
|
|
||||||
properties.addAll(extraProperties);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ArrayList<String> properties = new ArrayList<>(update.getPayload().getProperties());
|
||||||
|
properties.addAll(update.getExtraProperties());
|
||||||
|
|
||||||
try {
|
try {
|
||||||
mUpdateEngine.applyPayload(
|
mUpdateEngine.applyPayload(
|
||||||
payloadSpec.getUrl(),
|
update.getPayload().getUrl(),
|
||||||
payloadSpec.getOffset(),
|
update.getPayload().getOffset(),
|
||||||
payloadSpec.getSize(),
|
update.getPayload().getSize(),
|
||||||
properties.toArray(new String[0]));
|
properties.toArray(new String[0]));
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
Log.e(TAG, "UpdateEngine failed to apply the update", e);
|
Log.e(TAG, "UpdateEngine failed to apply the update", e);
|
||||||
@@ -328,6 +336,19 @@ public class UpdateManager {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void updateEngineReApplyPayload() {
|
||||||
|
UpdateData lastUpdate;
|
||||||
|
synchronized (mLock) {
|
||||||
|
// mLastPayloadSpec might be empty in some cases.
|
||||||
|
// But to make this sample app simple, we will not handle it.
|
||||||
|
Preconditions.checkArgument(
|
||||||
|
mLastUpdateData != null,
|
||||||
|
"mLastUpdateData must be present.");
|
||||||
|
lastUpdate = mLastUpdateData;
|
||||||
|
}
|
||||||
|
updateEngineApplyPayload(lastUpdate);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets the new slot that has the updated partitions as the active slot,
|
* Sets the new slot that has the updated partitions as the active slot,
|
||||||
* which device will boot into next time.
|
* which device will boot into next time.
|
||||||
@@ -342,12 +363,20 @@ public class UpdateManager {
|
|||||||
*/
|
*/
|
||||||
public void setSwitchSlotOnReboot() {
|
public void setSwitchSlotOnReboot() {
|
||||||
Log.d(TAG, "setSwitchSlotOnReboot invoked");
|
Log.d(TAG, "setSwitchSlotOnReboot invoked");
|
||||||
List<String> extraProperties = new ArrayList<>();
|
UpdateData.Builder builder;
|
||||||
|
synchronized (mLock) {
|
||||||
|
// To make sample app simple, we don't handle it.
|
||||||
|
Preconditions.checkArgument(
|
||||||
|
mLastUpdateData != null,
|
||||||
|
"mLastUpdateData must be present.");
|
||||||
|
builder = mLastUpdateData.toBuilder();
|
||||||
|
}
|
||||||
// PROPERTY_SKIP_POST_INSTALL should be passed on to skip post-installation hooks.
|
// PROPERTY_SKIP_POST_INSTALL should be passed on to skip post-installation hooks.
|
||||||
extraProperties.add(UpdateEngineProperties.PROPERTY_SKIP_POST_INSTALL);
|
builder.setExtraProperties(
|
||||||
// It sets property SWITCH_SLOT_ON_REBOOT=1 by default.
|
Collections.singletonList(UpdateEngineProperties.PROPERTY_SKIP_POST_INSTALL));
|
||||||
|
// UpdateEngine sets property SWITCH_SLOT_ON_REBOOT=1 by default.
|
||||||
// HTTP headers are not required, UpdateEngine is not expected to stream payload.
|
// HTTP headers are not required, UpdateEngine is not expected to stream payload.
|
||||||
updateEngineApplyPayload(mLastPayloadSpec, extraProperties);
|
updateEngineApplyPayload(builder.build());
|
||||||
}
|
}
|
||||||
|
|
||||||
private void onStatusUpdate(int status, float progress) {
|
private void onStatusUpdate(int status, float progress) {
|
||||||
@@ -391,4 +420,67 @@ public class UpdateManager {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* Contains update data - PayloadSpec and extra properties list.
|
||||||
|
*
|
||||||
|
* <p>{@code mPayload} contains url, offset and size to {@code PAYLOAD_BINARY_FILE_NAME}.
|
||||||
|
* {@code mExtraProperties} is a list of additional properties to pass to
|
||||||
|
* {@link UpdateEngine#applyPayload}.</p>
|
||||||
|
*/
|
||||||
|
private static class UpdateData {
|
||||||
|
private final PayloadSpec mPayload;
|
||||||
|
private final ImmutableList<String> mExtraProperties;
|
||||||
|
|
||||||
|
public static Builder builder() {
|
||||||
|
return new Builder();
|
||||||
|
}
|
||||||
|
|
||||||
|
UpdateData(Builder builder) {
|
||||||
|
this.mPayload = builder.mPayload;
|
||||||
|
this.mExtraProperties = ImmutableList.copyOf(builder.mExtraProperties);
|
||||||
|
}
|
||||||
|
|
||||||
|
public PayloadSpec getPayload() {
|
||||||
|
return mPayload;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ImmutableList<String> getExtraProperties() {
|
||||||
|
return mExtraProperties;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Builder toBuilder() {
|
||||||
|
return builder()
|
||||||
|
.setPayload(mPayload)
|
||||||
|
.setExtraProperties(mExtraProperties);
|
||||||
|
}
|
||||||
|
|
||||||
|
static class Builder {
|
||||||
|
private PayloadSpec mPayload;
|
||||||
|
private List<String> mExtraProperties;
|
||||||
|
|
||||||
|
public Builder setPayload(PayloadSpec payload) {
|
||||||
|
this.mPayload = payload;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Builder setExtraProperties(List<String> extraProperties) {
|
||||||
|
this.mExtraProperties = new ArrayList<>(extraProperties);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Builder addExtraProperty(String property) {
|
||||||
|
if (this.mExtraProperties == null) {
|
||||||
|
this.mExtraProperties = new ArrayList<>();
|
||||||
|
}
|
||||||
|
this.mExtraProperties.add(property);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public UpdateData build() {
|
||||||
|
return new UpdateData(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user