Merge "updater_sample: add UpdaterState"
am: 721f6d851f
Change-Id: Ic5f9ecadcb2af07048dd60660c1fbb64591aa547
This commit is contained in:
@@ -25,7 +25,6 @@ import com.example.android.systemupdatersample.services.PrepareStreamingService;
|
|||||||
import com.example.android.systemupdatersample.util.PayloadSpecs;
|
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.google.common.base.Preconditions;
|
import com.google.common.base.Preconditions;
|
||||||
import com.google.common.collect.ImmutableList;
|
import com.google.common.collect.ImmutableList;
|
||||||
import com.google.common.util.concurrent.AtomicDouble;
|
import com.google.common.util.concurrent.AtomicDouble;
|
||||||
@@ -59,7 +58,7 @@ 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 UpdaterState mUpdaterState = new UpdaterState(UpdaterState.IDLE);
|
||||||
|
|
||||||
private AtomicBoolean mManualSwitchSlotRequired = new AtomicBoolean(true);
|
private AtomicBoolean mManualSwitchSlotRequired = new AtomicBoolean(true);
|
||||||
|
|
||||||
@@ -111,7 +110,7 @@ public class UpdateManager {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets SystemUpdaterSample app state change callback. Value of {@code state} will be one
|
* Sets SystemUpdaterSample app state change callback. Value of {@code state} will be one
|
||||||
* of the values from {@link UpdaterStates}.
|
* of the values from {@link UpdaterState}.
|
||||||
*
|
*
|
||||||
* @param onStateChangeCallback a callback with parameter {@code state}.
|
* @param onStateChangeCallback a callback with parameter {@code state}.
|
||||||
*/
|
*/
|
||||||
@@ -193,8 +192,14 @@ public class UpdateManager {
|
|||||||
* it also notifies {@link this.mOnStateChangeCallback}.
|
* it also notifies {@link this.mOnStateChangeCallback}.
|
||||||
*/
|
*/
|
||||||
private void setUpdaterState(int updaterState) {
|
private void setUpdaterState(int updaterState) {
|
||||||
int previousState = mState.get();
|
int previousState = mUpdaterState.get();
|
||||||
mState.set(updaterState);
|
try {
|
||||||
|
mUpdaterState.set(updaterState);
|
||||||
|
} catch (UpdaterState.InvalidTransitionException e) {
|
||||||
|
// Note: invalid state transitions should be handled properly,
|
||||||
|
// but to make sample app simple, we just throw runtime exception.
|
||||||
|
throw new RuntimeException("Can't set state " + updaterState, e);
|
||||||
|
}
|
||||||
if (previousState != updaterState) {
|
if (previousState != updaterState) {
|
||||||
getOnStateChangeCallback().ifPresent(callback -> callback.accept(updaterState));
|
getOnStateChangeCallback().ifPresent(callback -> callback.accept(updaterState));
|
||||||
}
|
}
|
||||||
@@ -211,7 +216,7 @@ public class UpdateManager {
|
|||||||
public void cancelRunningUpdate() {
|
public void cancelRunningUpdate() {
|
||||||
try {
|
try {
|
||||||
mUpdateEngine.cancel();
|
mUpdateEngine.cancel();
|
||||||
setUpdaterState(UpdaterStates.IDLE);
|
setUpdaterState(UpdaterState.IDLE);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
Log.w(TAG, "UpdateEngine failed to stop the ongoing update", e);
|
Log.w(TAG, "UpdateEngine failed to stop the ongoing update", e);
|
||||||
}
|
}
|
||||||
@@ -227,7 +232,7 @@ public class UpdateManager {
|
|||||||
public void resetUpdate() {
|
public void resetUpdate() {
|
||||||
try {
|
try {
|
||||||
mUpdateEngine.resetStatus();
|
mUpdateEngine.resetStatus();
|
||||||
setUpdaterState(UpdaterStates.IDLE);
|
setUpdaterState(UpdaterState.IDLE);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
Log.w(TAG, "UpdateEngine failed to reset the update", e);
|
Log.w(TAG, "UpdateEngine failed to reset the update", e);
|
||||||
}
|
}
|
||||||
@@ -241,7 +246,7 @@ public class UpdateManager {
|
|||||||
*/
|
*/
|
||||||
public void applyUpdate(Context context, UpdateConfig config) {
|
public void applyUpdate(Context context, UpdateConfig config) {
|
||||||
mEngineErrorCode.set(UpdateEngineErrorCodes.UNKNOWN);
|
mEngineErrorCode.set(UpdateEngineErrorCodes.UNKNOWN);
|
||||||
setUpdaterState(UpdaterStates.RUNNING);
|
setUpdaterState(UpdaterState.RUNNING);
|
||||||
|
|
||||||
synchronized (mLock) {
|
synchronized (mLock) {
|
||||||
// Cleaning up previous update data.
|
// Cleaning up previous update data.
|
||||||
@@ -269,7 +274,7 @@ public class UpdateManager {
|
|||||||
builder.setPayload(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(UpdaterState.ERROR);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
updateEngineApplyPayload(builder.build());
|
updateEngineApplyPayload(builder.build());
|
||||||
@@ -290,7 +295,7 @@ public class UpdateManager {
|
|||||||
updateEngineApplyPayload(builder.build());
|
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(UpdaterState.ERROR);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -332,7 +337,7 @@ public class UpdateManager {
|
|||||||
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);
|
||||||
setUpdaterState(UpdaterStates.ERROR);
|
setUpdaterState(UpdaterState.ERROR);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -396,9 +401,11 @@ public class UpdateManager {
|
|||||||
mEngineErrorCode.set(errorCode);
|
mEngineErrorCode.set(errorCode);
|
||||||
if (errorCode == UpdateEngine.ErrorCodeConstants.SUCCESS
|
if (errorCode == UpdateEngine.ErrorCodeConstants.SUCCESS
|
||||||
|| errorCode == UpdateEngineErrorCodes.UPDATED_BUT_NOT_ACTIVE) {
|
|| errorCode == UpdateEngineErrorCodes.UPDATED_BUT_NOT_ACTIVE) {
|
||||||
setUpdaterState(UpdaterStates.FINISHED);
|
setUpdaterState(isManualSwitchSlotRequired()
|
||||||
|
? UpdaterState.SLOT_SWITCH_REQUIRED
|
||||||
|
: UpdaterState.REBOOT_REQUIRED);
|
||||||
} else if (errorCode != UpdateEngineErrorCodes.USER_CANCELLED) {
|
} else if (errorCode != UpdateEngineErrorCodes.USER_CANCELLED) {
|
||||||
setUpdaterState(UpdaterStates.ERROR);
|
setUpdaterState(UpdaterState.ERROR);
|
||||||
}
|
}
|
||||||
|
|
||||||
getOnEngineCompleteCallback()
|
getOnEngineCompleteCallback()
|
||||||
|
|||||||
@@ -0,0 +1,103 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2018 The Android Open Source Project
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.example.android.systemupdatersample;
|
||||||
|
|
||||||
|
import android.util.SparseArray;
|
||||||
|
|
||||||
|
import com.google.common.collect.ImmutableMap;
|
||||||
|
import com.google.common.collect.ImmutableSet;
|
||||||
|
|
||||||
|
import java.util.concurrent.atomic.AtomicInteger;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Controls updater state.
|
||||||
|
*/
|
||||||
|
public class UpdaterState {
|
||||||
|
|
||||||
|
public static final int IDLE = 0;
|
||||||
|
public static final int ERROR = 1;
|
||||||
|
public static final int RUNNING = 2;
|
||||||
|
public static final int PAUSED = 3;
|
||||||
|
public static final int SLOT_SWITCH_REQUIRED = 4;
|
||||||
|
public static final int REBOOT_REQUIRED = 5;
|
||||||
|
|
||||||
|
private static final SparseArray<String> STATE_MAP = new SparseArray<>();
|
||||||
|
|
||||||
|
static {
|
||||||
|
STATE_MAP.put(0, "IDLE");
|
||||||
|
STATE_MAP.put(1, "ERROR");
|
||||||
|
STATE_MAP.put(2, "RUNNING");
|
||||||
|
STATE_MAP.put(3, "PAUSED");
|
||||||
|
STATE_MAP.put(4, "SLOT_SWITCH_REQUIRED");
|
||||||
|
STATE_MAP.put(5, "REBOOT_REQUIRED");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Allowed state transitions. It's a map: key is a state, value is a set of states that
|
||||||
|
* are allowed to transition to from key.
|
||||||
|
*/
|
||||||
|
private static final ImmutableMap<Integer, ImmutableSet<Integer>> TRANSITIONS =
|
||||||
|
ImmutableMap.of(
|
||||||
|
IDLE, ImmutableSet.of(RUNNING),
|
||||||
|
RUNNING, ImmutableSet.of(ERROR, PAUSED, REBOOT_REQUIRED, SLOT_SWITCH_REQUIRED),
|
||||||
|
PAUSED, ImmutableSet.of(RUNNING),
|
||||||
|
SLOT_SWITCH_REQUIRED, ImmutableSet.of(ERROR)
|
||||||
|
);
|
||||||
|
|
||||||
|
private AtomicInteger mState;
|
||||||
|
|
||||||
|
public UpdaterState(int state) {
|
||||||
|
this.mState = new AtomicInteger(state);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns updater state.
|
||||||
|
*/
|
||||||
|
public int get() {
|
||||||
|
return mState.get();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the updater state.
|
||||||
|
*
|
||||||
|
* @throws InvalidTransitionException if transition is not allowed.
|
||||||
|
*/
|
||||||
|
public void set(int newState) throws InvalidTransitionException {
|
||||||
|
int oldState = mState.get();
|
||||||
|
if (!TRANSITIONS.get(oldState).contains(newState)) {
|
||||||
|
throw new InvalidTransitionException(
|
||||||
|
"Can't transition from " + oldState + " to " + newState);
|
||||||
|
}
|
||||||
|
mState.set(newState);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Converts status code to status name.
|
||||||
|
*/
|
||||||
|
public static String getStateText(int state) {
|
||||||
|
return STATE_MAP.get(state);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Defines invalid state transition exception.
|
||||||
|
*/
|
||||||
|
public static class InvalidTransitionException extends Exception {
|
||||||
|
public InvalidTransitionException(String msg) {
|
||||||
|
super(msg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -33,11 +33,11 @@ import android.widget.TextView;
|
|||||||
import com.example.android.systemupdatersample.R;
|
import com.example.android.systemupdatersample.R;
|
||||||
import com.example.android.systemupdatersample.UpdateConfig;
|
import com.example.android.systemupdatersample.UpdateConfig;
|
||||||
import com.example.android.systemupdatersample.UpdateManager;
|
import com.example.android.systemupdatersample.UpdateManager;
|
||||||
|
import com.example.android.systemupdatersample.UpdaterState;
|
||||||
import com.example.android.systemupdatersample.util.PayloadSpecs;
|
import com.example.android.systemupdatersample.util.PayloadSpecs;
|
||||||
import com.example.android.systemupdatersample.util.UpdateConfigs;
|
import com.example.android.systemupdatersample.util.UpdateConfigs;
|
||||||
import com.example.android.systemupdatersample.util.UpdateEngineErrorCodes;
|
import com.example.android.systemupdatersample.util.UpdateEngineErrorCodes;
|
||||||
import com.example.android.systemupdatersample.util.UpdateEngineStatuses;
|
import com.example.android.systemupdatersample.util.UpdateEngineStatuses;
|
||||||
import com.example.android.systemupdatersample.util.UpdaterStates;
|
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
@@ -192,7 +192,7 @@ public class MainActivity extends Activity {
|
|||||||
/**
|
/**
|
||||||
* Invoked when SystemUpdaterSample app state changes.
|
* Invoked when SystemUpdaterSample app state changes.
|
||||||
* Value of {@code state} will be one of the
|
* Value of {@code state} will be one of the
|
||||||
* values from {@link UpdaterStates}.
|
* values from {@link UpdaterState}.
|
||||||
*/
|
*/
|
||||||
private void onUpdaterStateChange(int state) {
|
private void onUpdaterStateChange(int state) {
|
||||||
Log.i(TAG, "onUpdaterStateChange invoked state=" + state);
|
Log.i(TAG, "onUpdaterStateChange invoked state=" + state);
|
||||||
@@ -233,8 +233,8 @@ public class MainActivity extends Activity {
|
|||||||
runOnUiThread(() -> {
|
runOnUiThread(() -> {
|
||||||
Log.i(TAG,
|
Log.i(TAG,
|
||||||
"Completed - errorCode="
|
"Completed - errorCode="
|
||||||
+ UpdateEngineErrorCodes.getCodeName(errorCode) + "/" + errorCode
|
+ UpdateEngineErrorCodes.getCodeName(errorCode) + "/" + errorCode
|
||||||
+ " " + completionState);
|
+ " " + completionState);
|
||||||
setUiEngineErrorCode(errorCode);
|
setUiEngineErrorCode(errorCode);
|
||||||
if (errorCode == UpdateEngineErrorCodes.UPDATED_BUT_NOT_ACTIVE) {
|
if (errorCode == UpdateEngineErrorCodes.UPDATED_BUT_NOT_ACTIVE) {
|
||||||
// if update was successfully applied.
|
// if update was successfully applied.
|
||||||
@@ -323,7 +323,7 @@ public class MainActivity extends Activity {
|
|||||||
* @param state updater sample state
|
* @param state updater sample state
|
||||||
*/
|
*/
|
||||||
private void setUiUpdaterState(int state) {
|
private void setUiUpdaterState(int state) {
|
||||||
String stateText = UpdaterStates.getStateText(state);
|
String stateText = UpdaterState.getStateText(state);
|
||||||
mTextViewUpdaterState.setText(stateText + "/" + state);
|
mTextViewUpdaterState.setText(stateText + "/" + state);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,50 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (C) 2018 The Android Open Source Project
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package com.example.android.systemupdatersample.util;
|
|
||||||
|
|
||||||
import android.util.SparseArray;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* SystemUpdaterSample app state.
|
|
||||||
*/
|
|
||||||
public class UpdaterStates {
|
|
||||||
|
|
||||||
public static final int IDLE = 0;
|
|
||||||
public static final int ERROR = 1;
|
|
||||||
public static final int RUNNING = 2;
|
|
||||||
public static final int PAUSED = 3;
|
|
||||||
public static final int FINISHED = 4;
|
|
||||||
|
|
||||||
private static final SparseArray<String> STATE_MAP = new SparseArray<>();
|
|
||||||
|
|
||||||
static {
|
|
||||||
STATE_MAP.put(0, "IDLE");
|
|
||||||
STATE_MAP.put(1, "ERROR");
|
|
||||||
STATE_MAP.put(2, "RUNNING");
|
|
||||||
STATE_MAP.put(3, "PAUSED");
|
|
||||||
STATE_MAP.put(4, "FINISHED");
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* converts status code to status name
|
|
||||||
*/
|
|
||||||
public static String getStateText(int state) {
|
|
||||||
return STATE_MAP.get(state);
|
|
||||||
}
|
|
||||||
|
|
||||||
private UpdaterStates() {}
|
|
||||||
}
|
|
||||||
Reference in New Issue
Block a user