updater_sample: add http header demo

Added demo passing http headers to UpdateEngine#applyPayload.

Bug: 79483768
Test: manually
Change-Id: I3e9c812dba2066acadbcea8d07c933368806e20c
Signed-off-by: Zhomart Mukhamejanov <zhomart@google.com>
This commit is contained in:
Zhomart Mukhamejanov 2018-05-09 14:28:49 -07:00
parent daa86e9024
commit 6aa5fb0bbe
4 changed files with 51 additions and 13 deletions

View file

@ -61,6 +61,17 @@ purpose only.
6. Push OTA packages to the device.
## Sending HTTP headers from UpdateEngine
Sometimes OTA package server might require some HTTP headers to be present,
e.g. `Authorization` header to contain valid auth token. While performing
streaming update, `UpdateEngine` allows passing on certain HTTP headers;
as of writing this sample app, these headers are `Authorization` and `User-Agent`.
`android.os.UpdateEngine#applyPayload` contains information on
which HTTP headers are supported.
## Development
- [x] Create a UI with list of configs, current version,
@ -72,12 +83,12 @@ purpose only.
- [x] Prepare streaming update (partially downloading package)
- [x] Add applying streaming update
- [x] Add stop/reset the update
- [x] Add demo for passing HTTP headers to `UpdateEngine#applyPayload`
- [ ] Add tests for `MainActivity`
- [ ] Verify system partition checksum for package
- [ ] HAL compatibility check
- [ ] Change partition demo
- [ ] Verify system partition checksum for package
- [ ] Add non-A/B updates demo
- [ ] Add docs for passing HTTP headers to `UpdateEngine#applyPayload`
## Running tests

View file

@ -8,6 +8,7 @@
"ab_streaming_metadata": {
"__": "streaming_metadata is required only for streaming update",
"__property_files": "name, offset and size of files",
"__authorization": "it will be sent to OTA package server as value of HTTP header - Authorization",
"property_files": [
{
"__filename": "name of the file in package",
@ -17,6 +18,7 @@
"offset": 531,
"size": 5012323
}
]
],
"authorization": "Basic my-secret-token"
}
}

View file

@ -25,6 +25,7 @@ import org.json.JSONObject;
import java.io.File;
import java.io.Serializable;
import java.util.Optional;
/**
* An update description. It will be parsed from JSON, which is intended to
@ -78,7 +79,9 @@ public class UpdateConfig implements Parcelable {
p.getLong("offset"),
p.getLong("size"));
}
c.mAbStreamingMetadata = new StreamingMetadata(propertyFiles);
c.mAbStreamingMetadata = new StreamingMetadata(
propertyFiles,
meta.getString("authorization_token"));
}
c.mRawJson = json;
return c;
@ -178,17 +181,23 @@ public class UpdateConfig implements Parcelable {
/** defines beginning of update data in archive */
private PackageFile[] mPropertyFiles;
public StreamingMetadata() {
mPropertyFiles = new PackageFile[0];
}
/** 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) {
public StreamingMetadata(PackageFile[] propertyFiles, String authorization) {
this.mPropertyFiles = propertyFiles;
this.mAuthorization = authorization;
}
public PackageFile[] getPropertyFiles() {
return mPropertyFiles;
}
public Optional<String> getAuthorization() {
return Optional.of(mAuthorization);
}
}
/**
@ -224,7 +233,6 @@ public class UpdateConfig implements Parcelable {
public long getSize() {
return mSize;
}
}
}

View file

@ -41,6 +41,7 @@ import com.example.android.systemupdatersample.util.UpdateEngineErrorCodes;
import com.example.android.systemupdatersample.util.UpdateEngineStatuses;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.atomic.AtomicInteger;
@ -51,6 +52,10 @@ public class MainActivity extends Activity {
private static final String TAG = "MainActivity";
/** HTTP Header: User-Agent; it will be sent to the server when streaming the payload. */
private static final String HTTP_USER_AGENT = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) "
+ "AppleWebKit/537.36 (KHTML, like Gecko) Chrome/60.0.3112.113 Safari/537.36";
private TextView mTextViewBuild;
private Spinner mSpinnerConfigs;
private TextView mTextViewConfigsDirHint;
@ -295,12 +300,17 @@ public class MainActivity extends Activity {
.show();
return;
}
updateEngineApplyPayload(payload);
updateEngineApplyPayload(payload, null);
} else {
Log.d(TAG, "Starting PrepareStreamingService");
PrepareStreamingService.startService(this, config, (code, payloadSpec) -> {
if (code == PrepareStreamingService.RESULT_CODE_SUCCESS) {
updateEngineApplyPayload(payloadSpec);
List<String> extraProperties = new ArrayList<>();
extraProperties.add("USER_AGENT=" + HTTP_USER_AGENT);
config.getStreamingMetadata()
.getAuthorization()
.ifPresent(s -> extraProperties.add("AUTHORIZATION=" + s));
updateEngineApplyPayload(payloadSpec, extraProperties);
} else {
Log.e(TAG, "PrepareStreamingService failed, result code is " + code);
Toast.makeText(
@ -317,14 +327,21 @@ public class MainActivity extends Activity {
*
* UpdateEngine works asynchronously. This method doesn't wait until
* end of the update.
*
* @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) {
private void updateEngineApplyPayload(PayloadSpec payloadSpec, List<String> extraProperties) {
ArrayList<String> properties = new ArrayList<>(payloadSpec.getProperties());
if (extraProperties != null) {
properties.addAll(extraProperties);
}
try {
mUpdateEngine.applyPayload(
payloadSpec.getUrl(),
payloadSpec.getOffset(),
payloadSpec.getSize(),
payloadSpec.getProperties().toArray(new String[0]));
properties.toArray(new String[0]));
} catch (Exception e) {
Log.e(TAG, "UpdateEngine failed to apply the update", e);
Toast.makeText(