Snap for 13210474 from e68d0557eb32284ef4a0210f0f586840842d57dc to 25Q2-release

Change-Id: I62ec3fb0cbfea1866faa036706a872a3dc84a4c5
diff --git a/client/incremental.cpp b/client/incremental.cpp
index de93cb7..f6cf1b0 100644
--- a/client/incremental.cpp
+++ b/client/incremental.cpp
@@ -194,6 +194,9 @@
     auto pipe_write_fd_param = std::to_string(cast_handle_to_int(adb_get_os_handle(pipe_write_fd)));
     close_on_exec(pipe_read_fd);
 
+    // We spawn an incremental server that will be up until all blocks have been fed to the
+    // Package Manager. This could take a long time depending on the size of the files to
+    // stream so we use a process able to outlive adb.
     std::vector<std::string> args(std::move(files));
     args.insert(args.begin(), {"inc-server", fd_param, pipe_write_fd_param});
     auto child =
@@ -210,6 +213,9 @@
     auto killOnExit = [](Process* p) { p->kill(); };
     std::unique_ptr<Process, decltype(killOnExit)> serverKiller(&child, killOnExit);
 
+    // Block until the Package Manager has received enough blocks to declare the installation
+    // successful or failure. Meanwhile, the incremental server is still sending blocks to the
+    // device.
     Result result = wait_for_installation(pipe_read_fd);
     adb_close(pipe_read_fd);
 
@@ -225,6 +231,9 @@
     return child;
 }
 
+// Wait until the Package Manager returns either "Success" or "Failure". The streaming
+// may not have finished when this happens but PM received all the blocks is needs
+// to decide if installation was ok.
 Result wait_for_installation(int read_fd) {
     static constexpr int maxMessageSize = 256;
     std::vector<char> child_stdout(CHUNK_SIZE);
diff --git a/docs/dev/README.md b/docs/dev/README.md
index 81f0167..a590914 100644
--- a/docs/dev/README.md
+++ b/docs/dev/README.md
@@ -9,3 +9,4 @@
 - [How adbd starts](how_adbd_starts.md)
 - [How burst mode works](delayed_ack.md)
 - [How ADB Wifi works](adb_wifi.md)
+- [How ADB Incremental install works](incremental-install.md)
diff --git a/docs/dev/incremental-install.md b/docs/dev/incremental-install.md
new file mode 100644
index 0000000..f47be75
--- /dev/null
+++ b/docs/dev/incremental-install.md
@@ -0,0 +1,155 @@
+# How ADB incremental-install works
+
+The regular way an app is installed on an Android devices is for ADB to open a
+connection to the package manager (`pm`) and write all the bytes. Once received
+by `pm`, the app is verified via v2 signature checking, adb gets an
+installation reply (SUCCESS or FAILURE [..]), and the operation is considered
+over.
+
+Incremental-install is a departure from the idea that all bytes needs to be
+pushed for the installation to be considered over. It even allows an app to
+start before `pm` has received all the bytes.
+
+## The big picture
+
+The big picture of incremental-install revolves around four concepts.
+
+- Blocks
+- Block requests
+- Incremental Server (`IS`)
+- V4 signature
+
+Each file of an app (apk, splits, obb) are viewed as a series of blocks.
+
+In incremental-install mode, `pm` only need to receive a few blocks to validate
+the app and declare installation over (with SUCCESS/FAILURE) which increase
+installation speed tremendously.
+
+In the background, ADB will keep on steaming blocks linearly, even after `pm`
+reported being "done". The background streaming is done in ADB's embedded
+`IS`.
+
+The `IS` sends blocks to the device in order it assumes will be accessed by `pm`.
+And then it sends the remaining block from start to end of file.
+
+`pm` will inevitably need blocks it has not received yet. For example, when the
+app's Central Directory (located at the end of a zip file) must be read to know
+what files are in the apk. This is where block requests enter the picture. The
+Android device can issue requests which will make the `IS` bump the priority of
+a block so it is sent to the device as soon as possible.
+
+### Incremental-install filesystem
+
+The block requests are not issued by Android Frameworks. Framework is completely
+oblivious of the background streaming. Everything is done at the Android kernel
+level where file access is detected. If a read lands on a block that has not been
+received yet, the kernel issues a block request to get it from the streaming
+server immediately.
+
+### App verification
+
+In incremental-install mode, `pm` does minimal verification of app integrity.
+- Checks that there is a v4 signature
+- Check there is a v2 or v3 signature
+- Check that v4 is linked to either v2 or v3
+- Check the v4 header is signed with same certificate as v2/v3
+
+The rest of the app verification is done by the Android kernel for each block level
+when they are received.
+
+With v2 signing, an apps is signed by building a merkle tree, keeping only the
+top node hash, signing it, and embedding it in the apk. On `pm` side, to verify
+the app, the merkle tree is rebuilt, and the top hash is compared against the
+signed hash. V2 can only work if `pm` has all the bytes of an app which is not
+the case here.
+
+#### v4 signing
+This problem is solved with V4 signing which does not discard the merkle tree
+but embed it in the signed file and also outputs the top merkle node hash in
+a .idsig file.
+
+Upon installation the whole merkel tree from V4 is given to `pm` which forwards
+it to the Android kernel. The kernel is in charge of verifying the integrity
+of each block when they are received from the `IS` via the merkle tree.
+
+For more details about v4 signing, refer to [APK signature scheme v4](https://source.android.com/docs/security/features/apksigning/v4) page.
+## How ADB performs incremental-install
+
+To perform incremental-install, ADB needs to do two things.
+
+- Define the block database to `pm`.
+- Start a `IS`.
+
+```
+  ┌───┐                              ┌────┐      
+  │adb│                              │ppm │      
+  └─┬─┘                              └─┬──┘      
+    │       pm install-incremental     │         
+    ├─────────────────────────────────►│         
+    │    ┌────┐                        │         
+    ├───►│ IS │                        │         
+    │    └─┬──┘                        │         
+    X      │                           │         
+           ├──────────────────────────►│         
+           ├──────────────────────────►│         
+           │◄──────────────────────────┤         
+           ├──────────────────────────►│         
+           │                           │         
+```
+
+### Local database
+
+The call to `pm incremental-install` has arguments describing the `IS` database.
+It allows the kernel to issue block requests. The arg format to describe the `IS`
+database is as follows.
+
+```
+filename:file_size:file_id:signature[:protocol_version]
+```
+
+where
+
+- `file_id` is the identified that will be used by the kernel for block
+requests. There is one arg for each file to be streamed.
+- `signature` is the top merkle hash.
+- `[:protocol_version]` is optional.
+
+### Unsigned files
+
+There could be unsigned files to be installed. In this case, `pm` has to be made
+aware of them via a special arg format.
+
+```
+filename::file_size:file_id
+```
+
+These files are not sent via the `IS` but instead sent on stdin, before
+the `IS` is started.
+
+```
+  ┌───┐                              ┌────┐      
+  │adb│                              │ppm │      
+  └─┬─┘                              └─┬──┘      
+    │       pm install-incremental     │         
+    ├─────────────────────────────────►│         
+    │                                  │         
+    │       (stdin) write(unsigned)    │         
+    ├─────────────────────────────────►│         
+    │    ┌────┐                        │         
+    ├───►│ IS │                        │         
+    │    └─┬──┘                        │         
+    X      │                           │         
+           ├──────────────────────────►│         
+           ├──────────────────────────►│         
+           │◄──────────────────────────┤         
+           ├──────────────────────────►│         
+           │                           │         
+```
+
+## Learn more
+
+There is more documentation about this topic which is unfortunately internal only.
+
+- [go/incremental-adb](go/incremental-adb)
+- [go/apk-v4-signature-format](go/apk-v4-signature-format)
+- [go/instamatic-design-signature](go/instamatic-design-signature)
\ No newline at end of file