xref: /aosp_15_r20/bootable/recovery/updater_sample/README.md (revision e7c364b630b241adcb6c7726a21055250b91fdac)
1*e7c364b6SAndroid Build Coastguard Worker# SystemUpdaterSample
2*e7c364b6SAndroid Build Coastguard Worker
3*e7c364b6SAndroid Build Coastguard WorkerThis app demonstrates how to use Android system updates APIs to install
4*e7c364b6SAndroid Build Coastguard Worker[OTA updates](https://source.android.com/devices/tech/ota/). It contains a
5*e7c364b6SAndroid Build Coastguard Workersample client for `update_engine` to install A/B (seamless) updates.
6*e7c364b6SAndroid Build Coastguard Worker
7*e7c364b6SAndroid Build Coastguard WorkerA/B (seamless) update is available since Android Nougat (API 24), but this sample
8*e7c364b6SAndroid Build Coastguard Workertargets the latest android.
9*e7c364b6SAndroid Build Coastguard Worker
10*e7c364b6SAndroid Build Coastguard Worker
11*e7c364b6SAndroid Build Coastguard Worker## Workflow
12*e7c364b6SAndroid Build Coastguard Worker
13*e7c364b6SAndroid Build Coastguard WorkerSystemUpdaterSample app shows list of available updates on the UI. User is allowed
14*e7c364b6SAndroid Build Coastguard Workerto select an update and apply it to the device. App shows installation progress,
15*e7c364b6SAndroid Build Coastguard Workerlogs can be found in `adb logcat`. User can stop or reset an update. Resetting
16*e7c364b6SAndroid Build Coastguard Workerthe update requests update engine to cancel any ongoing update, and revert
17*e7c364b6SAndroid Build Coastguard Workerif the update has been applied. Stopping does not revert the applied update.
18*e7c364b6SAndroid Build Coastguard Worker
19*e7c364b6SAndroid Build Coastguard Worker
20*e7c364b6SAndroid Build Coastguard Worker## Update Config file
21*e7c364b6SAndroid Build Coastguard Worker
22*e7c364b6SAndroid Build Coastguard WorkerIn this sample updates are defined in JSON update config files.
23*e7c364b6SAndroid Build Coastguard WorkerThe structure of a config file is defined in
24*e7c364b6SAndroid Build Coastguard Worker`com.example.android.systemupdatersample.UpdateConfig`, example file is located
25*e7c364b6SAndroid Build Coastguard Workerat `res/raw/sample.json`.
26*e7c364b6SAndroid Build Coastguard Worker
27*e7c364b6SAndroid Build Coastguard WorkerIn real-life update system the config files expected to be served from a server
28*e7c364b6SAndroid Build Coastguard Workerto the app, but in this sample, the config files are stored on the device.
29*e7c364b6SAndroid Build Coastguard WorkerThe directory can be found in logs or on the UI. In most cases it should be located at
30*e7c364b6SAndroid Build Coastguard Worker`/data/user/0/com.example.android.systemupdatersample/files/configs/`.
31*e7c364b6SAndroid Build Coastguard Worker
32*e7c364b6SAndroid Build Coastguard WorkerSystemUpdaterSample app downloads OTA package from `url`. In this sample app
33*e7c364b6SAndroid Build Coastguard Worker`url` is expected to point to file system, e.g. `file:///data/my-sample-ota-builds-dir/ota-002.zip`.
34*e7c364b6SAndroid Build Coastguard Worker
35*e7c364b6SAndroid Build Coastguard WorkerIf `ab_install_type` is `NON_STREAMING` then app checks if `url` starts
36*e7c364b6SAndroid Build Coastguard Workerwith `file://` and passes `url` to the `update_engine`.
37*e7c364b6SAndroid Build Coastguard Worker
38*e7c364b6SAndroid Build Coastguard WorkerIf `ab_install_type` is `STREAMING`, app downloads only the entries in need, as
39*e7c364b6SAndroid Build Coastguard Workeropposed to the entire package, to initiate a streaming update. The `payload.bin`
40*e7c364b6SAndroid Build Coastguard Workerentry, which takes up the majority of the space in an OTA package, will be
41*e7c364b6SAndroid Build Coastguard Workerstreamed by `update_engine` directly. The ZIP entries in such a package need to be
42*e7c364b6SAndroid Build Coastguard Workersaved uncompressed (`ZIP_STORED`), so that their data can be downloaded directly
43*e7c364b6SAndroid Build Coastguard Workerwith the offset and length. As `payload.bin` itself is already in compressed
44*e7c364b6SAndroid Build Coastguard Workerformat, the size penalty is marginal.
45*e7c364b6SAndroid Build Coastguard Worker
46*e7c364b6SAndroid Build Coastguard Workerif `ab_config.force_switch_slot` set true device will boot to the
47*e7c364b6SAndroid Build Coastguard Workerupdated partition on next reboot; otherwise button "Switch Slot" will
48*e7c364b6SAndroid Build Coastguard Workerbecome active, and user can manually set updated partition as the active slot.
49*e7c364b6SAndroid Build Coastguard Worker
50*e7c364b6SAndroid Build Coastguard WorkerConfig files can be generated using `tools/gen_update_config.py`.
51*e7c364b6SAndroid Build Coastguard WorkerRunning `./tools/gen_update_config.py --help` shows usage of the script.
52*e7c364b6SAndroid Build Coastguard Worker
53*e7c364b6SAndroid Build Coastguard Worker
54*e7c364b6SAndroid Build Coastguard Worker## Sample App State vs UpdateEngine Status
55*e7c364b6SAndroid Build Coastguard Worker
56*e7c364b6SAndroid Build Coastguard WorkerUpdateEngine provides status for different stages of update application
57*e7c364b6SAndroid Build Coastguard Workerprocess. But it lacks of proper status codes when update fails.
58*e7c364b6SAndroid Build Coastguard Worker
59*e7c364b6SAndroid Build Coastguard WorkerThis creates two problems:
60*e7c364b6SAndroid Build Coastguard Worker
61*e7c364b6SAndroid Build Coastguard Worker1. If sample app is unbound from update_engine (MainActivity is paused, destroyed),
62*e7c364b6SAndroid Build Coastguard Worker   app doesn't receive onStatusUpdate and onPayloadApplicationCompleted notifications.
63*e7c364b6SAndroid Build Coastguard Worker   If app binds to update_engine after update is completed,
64*e7c364b6SAndroid Build Coastguard Worker   only onStatusUpdate is called, but status becomes IDLE in most cases.
65*e7c364b6SAndroid Build Coastguard Worker   And there is no way to know if update was successful or not.
66*e7c364b6SAndroid Build Coastguard Worker
67*e7c364b6SAndroid Build Coastguard Worker2. This sample app demostrates suspend/resume using update_engins's
68*e7c364b6SAndroid Build Coastguard Worker   `cancel` and `applyPayload` (which picks up from where it left).
69*e7c364b6SAndroid Build Coastguard Worker   When `cancel` is called, status is set to `IDLE`, which doesn't allow
70*e7c364b6SAndroid Build Coastguard Worker   tracking suspended state properly.
71*e7c364b6SAndroid Build Coastguard Worker
72*e7c364b6SAndroid Build Coastguard WorkerTo solve these problems sample app implements its own separate update
73*e7c364b6SAndroid Build Coastguard Workerstate - `UpdaterState`. To solve the first problem, sample app persists
74*e7c364b6SAndroid Build Coastguard Worker`UpdaterState` on a device. When app is resumed, it checks if `UpdaterState`
75*e7c364b6SAndroid Build Coastguard Workermatches the update_engine's status (as onStatusUpdate is guaranteed to be called).
76*e7c364b6SAndroid Build Coastguard WorkerIf they doesn't match, sample app calls `applyPayload` again with the same
77*e7c364b6SAndroid Build Coastguard Workerparameters, and handles update completion properly using `onPayloadApplicationCompleted`
78*e7c364b6SAndroid Build Coastguard Workercallback. The second problem is solved by adding `PAUSED` updater state.
79*e7c364b6SAndroid Build Coastguard Worker
80*e7c364b6SAndroid Build Coastguard Worker
81*e7c364b6SAndroid Build Coastguard Worker## Sample App UI
82*e7c364b6SAndroid Build Coastguard Worker
83*e7c364b6SAndroid Build Coastguard Worker### Text fields
84*e7c364b6SAndroid Build Coastguard Worker
85*e7c364b6SAndroid Build Coastguard Worker- `Current Build:` - shows current active build.
86*e7c364b6SAndroid Build Coastguard Worker- `Updater state:` - SystemUpdaterSample app state.
87*e7c364b6SAndroid Build Coastguard Worker- `Engine status:` - last reported update_engine status.
88*e7c364b6SAndroid Build Coastguard Worker- `Engine error:` - last reported payload application error.
89*e7c364b6SAndroid Build Coastguard Worker
90*e7c364b6SAndroid Build Coastguard Worker### Buttons
91*e7c364b6SAndroid Build Coastguard Worker
92*e7c364b6SAndroid Build Coastguard Worker- `Reload` - reloads update configs from device storage.
93*e7c364b6SAndroid Build Coastguard Worker- `View config` - shows selected update config.
94*e7c364b6SAndroid Build Coastguard Worker- `Apply` - applies selected update config.
95*e7c364b6SAndroid Build Coastguard Worker- `Stop` - cancel running update, calls `UpdateEngine#cancel`.
96*e7c364b6SAndroid Build Coastguard Worker- `Reset` - reset update, calls `UpdateEngine#resetStatus`, can be called
97*e7c364b6SAndroid Build Coastguard Worker            only when update is not running.
98*e7c364b6SAndroid Build Coastguard Worker- `Suspend` - suspend running update, uses `UpdateEngine#cancel`.
99*e7c364b6SAndroid Build Coastguard Worker- `Resume` - resumes suspended update, uses `UpdateEngine#applyPayload`.
100*e7c364b6SAndroid Build Coastguard Worker- `Switch Slot` - if `ab_config.force_switch_slot` config set true,
101*e7c364b6SAndroid Build Coastguard Worker            this button will be enabled after payload is applied,
102*e7c364b6SAndroid Build Coastguard Worker            to switch A/B slot on next reboot.
103*e7c364b6SAndroid Build Coastguard Worker
104*e7c364b6SAndroid Build Coastguard Worker
105*e7c364b6SAndroid Build Coastguard Worker## Sending HTTP headers from UpdateEngine
106*e7c364b6SAndroid Build Coastguard Worker
107*e7c364b6SAndroid Build Coastguard WorkerSometimes OTA package server might require some HTTP headers to be present,
108*e7c364b6SAndroid Build Coastguard Workere.g. `Authorization` header to contain valid auth token. While performing
109*e7c364b6SAndroid Build Coastguard Workerstreaming update, `UpdateEngine` allows passing on certain HTTP headers;
110*e7c364b6SAndroid Build Coastguard Workeras of writing this sample app, these headers are `Authorization` and `User-Agent`.
111*e7c364b6SAndroid Build Coastguard Worker
112*e7c364b6SAndroid Build Coastguard Worker`android.os.UpdateEngine#applyPayload` contains information on
113*e7c364b6SAndroid Build Coastguard Workerwhich HTTP headers are supported.
114*e7c364b6SAndroid Build Coastguard Worker
115*e7c364b6SAndroid Build Coastguard Worker
116*e7c364b6SAndroid Build Coastguard Worker## Used update_engine APIs
117*e7c364b6SAndroid Build Coastguard Worker
118*e7c364b6SAndroid Build Coastguard Worker### UpdateEngine#bind
119*e7c364b6SAndroid Build Coastguard Worker
120*e7c364b6SAndroid Build Coastguard WorkerBinds given callbacks to update_engine. When update_engine successfully
121*e7c364b6SAndroid Build Coastguard Workerinitialized, it's guaranteed to invoke callback onStatusUpdate.
122*e7c364b6SAndroid Build Coastguard Worker
123*e7c364b6SAndroid Build Coastguard Worker### UpdateEngine#applyPayload
124*e7c364b6SAndroid Build Coastguard Worker
125*e7c364b6SAndroid Build Coastguard WorkerStart an update attempt to download an apply the provided `payload_url` if
126*e7c364b6SAndroid Build Coastguard Workerno other update is running. The extra `key_value_pair_headers` will be
127*e7c364b6SAndroid Build Coastguard Workerincluded when fetching the payload.
128*e7c364b6SAndroid Build Coastguard Worker
129*e7c364b6SAndroid Build Coastguard Worker`key_value_pair_headers` argument also accepts properties other than HTTP Headers.
130*e7c364b6SAndroid Build Coastguard WorkerList of allowed properties can be found in `system/update_engine/common/constants.cc`.
131*e7c364b6SAndroid Build Coastguard Worker
132*e7c364b6SAndroid Build Coastguard Worker### UpdateEngine#cancel
133*e7c364b6SAndroid Build Coastguard Worker
134*e7c364b6SAndroid Build Coastguard WorkerCancel the ongoing update. The update could be running or suspended, but it
135*e7c364b6SAndroid Build Coastguard Workercan't be canceled after it was done.
136*e7c364b6SAndroid Build Coastguard Worker
137*e7c364b6SAndroid Build Coastguard Worker### UpdateEngine#resetStatus
138*e7c364b6SAndroid Build Coastguard Worker
139*e7c364b6SAndroid Build Coastguard WorkerReset the already applied update back to an idle state. This method can
140*e7c364b6SAndroid Build Coastguard Workeronly be called when no update attempt is going on, and it will reset the
141*e7c364b6SAndroid Build Coastguard Workerstatus back to idle, deleting the currently applied update if any.
142*e7c364b6SAndroid Build Coastguard Worker
143*e7c364b6SAndroid Build Coastguard Worker### Callback: onStatusUpdate
144*e7c364b6SAndroid Build Coastguard Worker
145*e7c364b6SAndroid Build Coastguard WorkerCalled whenever the value of `status` or `progress` changes. For
146*e7c364b6SAndroid Build Coastguard Worker`progress` values changes, this method will be called only if it changes significantly.
147*e7c364b6SAndroid Build Coastguard WorkerAt this time of writing this doc, delta for `progress` is `0.005`.
148*e7c364b6SAndroid Build Coastguard Worker
149*e7c364b6SAndroid Build Coastguard Worker`onStatusUpdate` is always called when app binds to update_engine,
150*e7c364b6SAndroid Build Coastguard Workerexcept when update_engine fails to initialize.
151*e7c364b6SAndroid Build Coastguard Worker
152*e7c364b6SAndroid Build Coastguard Worker### Callback: onPayloadApplicationComplete
153*e7c364b6SAndroid Build Coastguard Worker
154*e7c364b6SAndroid Build Coastguard WorkerCalled whenever an update attempt is completed or failed.
155*e7c364b6SAndroid Build Coastguard Worker
156*e7c364b6SAndroid Build Coastguard Worker
157*e7c364b6SAndroid Build Coastguard Worker## Running on a device
158*e7c364b6SAndroid Build Coastguard Worker
159*e7c364b6SAndroid Build Coastguard WorkerThe commands are expected to be run from `$ANDROID_BUILD_TOP` and for demo
160*e7c364b6SAndroid Build Coastguard Workerpurpose only.
161*e7c364b6SAndroid Build Coastguard Worker
162*e7c364b6SAndroid Build Coastguard Worker### Without the privileged system permissions
163*e7c364b6SAndroid Build Coastguard Worker
164*e7c364b6SAndroid Build Coastguard Worker1. Compile the app `mmma -j bootable/recovery/updater_sample`.
165*e7c364b6SAndroid Build Coastguard Worker2. Install the app to the device using `adb install <APK_PATH>`.
166*e7c364b6SAndroid Build Coastguard Worker3. Change permissions on `/data/ota_package/` to `0777` on the device.
167*e7c364b6SAndroid Build Coastguard Worker4. Set SELinux mode to permissive. See instructions below.
168*e7c364b6SAndroid Build Coastguard Worker5. Add update config files; look above at [Update Config file](#Update-Config-file).
169*e7c364b6SAndroid Build Coastguard Worker6. Push OTA packages to the device.
170*e7c364b6SAndroid Build Coastguard Worker7. Run the sample app.
171*e7c364b6SAndroid Build Coastguard Worker
172*e7c364b6SAndroid Build Coastguard Worker### With the privileged system permissions
173*e7c364b6SAndroid Build Coastguard Worker
174*e7c364b6SAndroid Build Coastguard WorkerTo run sample app as a privileged system app, it needs to be installed in `/system/priv-app/`.
175*e7c364b6SAndroid Build Coastguard WorkerThis directory is expected to be read-only, unless explicitly remounted.
176*e7c364b6SAndroid Build Coastguard Worker
177*e7c364b6SAndroid Build Coastguard WorkerThe recommended way to run the app is to build and install it as a
178*e7c364b6SAndroid Build Coastguard Workerprivileged system app, so it's granted the required permissions to access
179*e7c364b6SAndroid Build Coastguard Worker`update_engine` service as well as OTA package files. Detailed steps are as follows:
180*e7c364b6SAndroid Build Coastguard Worker
181*e7c364b6SAndroid Build Coastguard Worker1. [Prepare to build](https://source.android.com/setup/build/building)
182*e7c364b6SAndroid Build Coastguard Worker2. Add the module (SystemUpdaterSample) to the `PRODUCT_PACKAGES` list for the
183*e7c364b6SAndroid Build Coastguard Worker   lunch target.
184*e7c364b6SAndroid Build Coastguard Worker   e.g. add a line containing `PRODUCT_PACKAGES += SystemUpdaterSample`
185*e7c364b6SAndroid Build Coastguard Worker   to `device/google/marlin/device-common.mk`.
186*e7c364b6SAndroid Build Coastguard Worker3. [Whitelist the sample app](https://source.android.com/devices/tech/config/perms-whitelist)
187*e7c364b6SAndroid Build Coastguard Worker   * Add
188*e7c364b6SAndroid Build Coastguard Worker   ```
189*e7c364b6SAndroid Build Coastguard Worker    <privapp-permissions package="com.example.android.systemupdatersample">
190*e7c364b6SAndroid Build Coastguard Worker        <permission name="android.permission.ACCESS_CACHE_FILESYSTEM"/>
191*e7c364b6SAndroid Build Coastguard Worker    </privapp-permissions>
192*e7c364b6SAndroid Build Coastguard Worker   ```
193*e7c364b6SAndroid Build Coastguard Worker   to `frameworks/base/data/etc/privapp-permissions-platform.xml`
194*e7c364b6SAndroid Build Coastguard Worker4. Add `privileged: true` to SystemUpdaterSample
195*e7c364b6SAndroid Build Coastguard Worker   [building rule](https://android.googlesource.com/platform/bootable/recovery/+/refs/heads/master/updater_sample/Android.bp).
196*e7c364b6SAndroid Build Coastguard Worker5. Build sample app `make -j SystemUpdaterSample`.
197*e7c364b6SAndroid Build Coastguard Worker6. Build Android `make -j`
198*e7c364b6SAndroid Build Coastguard Worker7. [Flash the device](https://source.android.com/setup/build/running)
199*e7c364b6SAndroid Build Coastguard Worker8. Add update config files; look above at `## Update Config file`;
200*e7c364b6SAndroid Build Coastguard Worker   `adb root` might be required.
201*e7c364b6SAndroid Build Coastguard Worker9. Push OTA packages to the device if there is no server to stream packages from;
202*e7c364b6SAndroid Build Coastguard Worker   changing of SELinux labels of OTA packages directory might be required
203*e7c364b6SAndroid Build Coastguard Worker   `chcon -R u:object_r:ota_package_file:s0 /data/my-sample-ota-builds-dir`
204*e7c364b6SAndroid Build Coastguard Worker10. Run the sample app.
205*e7c364b6SAndroid Build Coastguard Worker
206*e7c364b6SAndroid Build Coastguard Worker
207*e7c364b6SAndroid Build Coastguard Worker## Development
208*e7c364b6SAndroid Build Coastguard Worker
209*e7c364b6SAndroid Build Coastguard Worker- [x] Create a UI with list of configs, current version,
210*e7c364b6SAndroid Build Coastguard Worker      control buttons, progress bar and log viewer
211*e7c364b6SAndroid Build Coastguard Worker- [x] Add `PayloadSpec` and `PayloadSpecs` for working with
212*e7c364b6SAndroid Build Coastguard Worker      update zip file
213*e7c364b6SAndroid Build Coastguard Worker- [x] Add `UpdateConfig` for working with json config files
214*e7c364b6SAndroid Build Coastguard Worker- [x] Add applying non-streaming update
215*e7c364b6SAndroid Build Coastguard Worker- [x] Prepare streaming update (partially downloading package)
216*e7c364b6SAndroid Build Coastguard Worker- [x] Add applying streaming update
217*e7c364b6SAndroid Build Coastguard Worker- [x] Add stop/reset the update
218*e7c364b6SAndroid Build Coastguard Worker- [x] Add demo for passing HTTP headers to `UpdateEngine#applyPayload`
219*e7c364b6SAndroid Build Coastguard Worker- [x] [Package compatibility check](https://source.android.com/devices/architecture/vintf/match-rules)
220*e7c364b6SAndroid Build Coastguard Worker- [x] Deferred switch slot demo
221*e7c364b6SAndroid Build Coastguard Worker- [x] Add UpdateManager; extract update logic from MainActivity
222*e7c364b6SAndroid Build Coastguard Worker- [x] Add Sample app update state (separate from update_engine status)
223*e7c364b6SAndroid Build Coastguard Worker- [x] Add smart update completion detection using onStatusUpdate
224*e7c364b6SAndroid Build Coastguard Worker- [x] Add pause/resume demo
225*e7c364b6SAndroid Build Coastguard Worker- [x] Verify system partition checksum for package
226*e7c364b6SAndroid Build Coastguard Worker
227*e7c364b6SAndroid Build Coastguard Worker
228*e7c364b6SAndroid Build Coastguard Worker## Running tests
229*e7c364b6SAndroid Build Coastguard Worker
230*e7c364b6SAndroid Build Coastguard WorkerThe commands are expected to be run from `$ANDROID_BUILD_TOP`.
231*e7c364b6SAndroid Build Coastguard Worker
232*e7c364b6SAndroid Build Coastguard Worker1. Build `make -j SystemUpdaterSample` and `make -j SystemUpdaterSampleTests`.
233*e7c364b6SAndroid Build Coastguard Worker2. Install app
234*e7c364b6SAndroid Build Coastguard Worker   `adb install $OUT/system/app/SystemUpdaterSample/SystemUpdaterSample.apk`
235*e7c364b6SAndroid Build Coastguard Worker3. Install tests
236*e7c364b6SAndroid Build Coastguard Worker   `adb install $OUT/testcases/SystemUpdaterSampleTests/arm64/SystemUpdaterSampleTests.apk`
237*e7c364b6SAndroid Build Coastguard Worker4. Run tests
238*e7c364b6SAndroid Build Coastguard Worker   `adb shell am instrument -w com.example.android.systemupdatersample.tests/android.support.test.runner.AndroidJUnitRunner`
239*e7c364b6SAndroid Build Coastguard Worker5. Run a test file
240*e7c364b6SAndroid Build Coastguard Worker   ```
241*e7c364b6SAndroid Build Coastguard Worker   adb shell am instrument \
242*e7c364b6SAndroid Build Coastguard Worker     -w -e class com.example.android.systemupdatersample.UpdateManagerTest#applyUpdate_appliesPayloadToUpdateEngine \
243*e7c364b6SAndroid Build Coastguard Worker     com.example.android.systemupdatersample.tests/android.support.test.runner.AndroidJUnitRunner
244*e7c364b6SAndroid Build Coastguard Worker   ```
245*e7c364b6SAndroid Build Coastguard Worker
246*e7c364b6SAndroid Build Coastguard Worker
247*e7c364b6SAndroid Build Coastguard Worker## Accessing `android.os.UpdateEngine` API
248*e7c364b6SAndroid Build Coastguard Worker
249*e7c364b6SAndroid Build Coastguard Worker`android.os.UpdateEngine` APIs are marked as `@SystemApi`, meaning only system
250*e7c364b6SAndroid Build Coastguard Workerapps can access them.
251*e7c364b6SAndroid Build Coastguard Worker
252*e7c364b6SAndroid Build Coastguard Worker
253*e7c364b6SAndroid Build Coastguard Worker## Getting read/write access to `/data/ota_package/`
254*e7c364b6SAndroid Build Coastguard Worker
255*e7c364b6SAndroid Build Coastguard WorkerAccess to cache filesystem is granted only to system apps.
256*e7c364b6SAndroid Build Coastguard Worker
257*e7c364b6SAndroid Build Coastguard Worker
258*e7c364b6SAndroid Build Coastguard Worker## Setting SELinux mode to permissive (0)
259*e7c364b6SAndroid Build Coastguard Worker
260*e7c364b6SAndroid Build Coastguard Worker```txt
261*e7c364b6SAndroid Build Coastguard Workerlocal$ adb root
262*e7c364b6SAndroid Build Coastguard Workerlocal$ adb shell
263*e7c364b6SAndroid Build Coastguard Workerandroid# setenforce 0
264*e7c364b6SAndroid Build Coastguard Workerandroid# getenforce
265*e7c364b6SAndroid Build Coastguard Worker```
266*e7c364b6SAndroid Build Coastguard Worker
267*e7c364b6SAndroid Build Coastguard Worker
268*e7c364b6SAndroid Build Coastguard Worker## License
269*e7c364b6SAndroid Build Coastguard Worker
270*e7c364b6SAndroid Build Coastguard WorkerSystemUpdaterSample app is released under
271*e7c364b6SAndroid Build Coastguard Worker[Apache License 2.0](https://www.apache.org/licenses/LICENSE-2.0).
272