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>
diff --git a/updater_sample/src/com/example/android/systemupdatersample/UpdateConfig.java b/updater_sample/src/com/example/android/systemupdatersample/UpdateConfig.java
index 1851724..b08bfd0 100644
--- a/updater_sample/src/com/example/android/systemupdatersample/UpdateConfig.java
+++ b/updater_sample/src/com/example/android/systemupdatersample/UpdateConfig.java
@@ -25,6 +25,7 @@
 
 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 @@
                         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 @@
         /** 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 long getSize() {
             return mSize;
         }
-
     }
 
 }
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 359e2b1..1708256 100644
--- a/updater_sample/src/com/example/android/systemupdatersample/ui/MainActivity.java
+++ b/updater_sample/src/com/example/android/systemupdatersample/ui/MainActivity.java
@@ -41,6 +41,7 @@
 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 @@
 
     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 @@
                         .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 @@
      *
      * 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(