File: DynamicSystemManager.java

package info (click to toggle)
android-platform-frameworks-base 1%3A14~beta1-3
  • links: PTS, VCS
  • area: main
  • in suites: trixie
  • size: 326,092 kB
  • sloc: java: 2,032,373; xml: 343,016; cpp: 304,181; python: 3,683; ansic: 2,090; sh: 1,871; makefile: 117; sed: 19
file content (288 lines) | stat: -rw-r--r-- 11,015 bytes parent folder | download | duplicates (3)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
/*
 * Copyright (C) 2019 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 android.os.image;

import android.annotation.NonNull;
import android.annotation.RequiresPermission;
import android.annotation.SystemService;
import android.content.Context;
import android.gsi.AvbPublicKey;
import android.gsi.GsiProgress;
import android.gsi.IGsiService;
import android.os.ParcelFileDescriptor;
import android.os.RemoteException;
import android.util.Pair;

/**
 * The DynamicSystemManager offers a mechanism to use a new system image temporarily. After the
 * installation, the device can reboot into this image with a new created /data. This image will
 * last until the next reboot and then the device will go back to the original image. However the
 * installed image and the new created /data are not deleted but disabled. Thus the application can
 * either re-enable the installed image by calling {@link #toggle} or use the {@link #remove} to
 * delete it completely. In other words, there are three device states: no installation, installed
 * and running. The procedure to install a DynamicSystem starts with a {@link #startInstallation},
 * followed by a series of {@link #write} and ends with a {@link commit}. Once the installation is
 * complete, the device state changes from no installation to the installed state and a followed
 * reboot will change its state to running. Note one instance of DynamicSystem can exist on a given
 * device thus the {@link #startInstallation} will fail if the device is currently running a
 * DynamicSystem.
 *
 * @hide
 */
@SystemService(Context.DYNAMIC_SYSTEM_SERVICE)
public class DynamicSystemManager {
    private static final String TAG = "DynamicSystemManager";

    private final IDynamicSystemService mService;

    /** {@hide} */
    public DynamicSystemManager(IDynamicSystemService service) {
        mService = service;
    }

    /** The DynamicSystemManager.Session represents a started session for the installation. */
    public class Session {
        private Session() {}

        /**
         * Set the file descriptor that points to a ashmem which will be used
         * to fetch data during the submitFromAshmem.
         *
         * @param ashmem fd that points to a ashmem
         * @param size size of the ashmem file
         */
        @RequiresPermission(android.Manifest.permission.MANAGE_DYNAMIC_SYSTEM)
        public boolean setAshmem(ParcelFileDescriptor ashmem, long size) {
            try {
                return mService.setAshmem(ashmem, size);
            } catch (RemoteException e) {
                throw new RuntimeException(e.toString());
            }
        }

        /**
         * Submit bytes to the DSU partition from the ashmem previously set with
         * setAshmem.
         *
         * @param size Number of bytes
         * @return true on success, false otherwise.
         */
        @RequiresPermission(android.Manifest.permission.MANAGE_DYNAMIC_SYSTEM)
        public boolean submitFromAshmem(int size) {
            try {
                return mService.submitFromAshmem(size);
            } catch (RemoteException e) {
                throw new RuntimeException(e.toString());
            }
        }

        /**
         * Retrieve AVB public key from installing partition.
         *
         * @param dst           Output the AVB public key.
         * @return              true on success, false if partition doesn't have a
         *                      valid VBMeta block to retrieve the AVB key from.
         */
        @RequiresPermission(android.Manifest.permission.MANAGE_DYNAMIC_SYSTEM)
        public boolean getAvbPublicKey(AvbPublicKey dst) {
            try {
                return mService.getAvbPublicKey(dst);
            } catch (RemoteException e) {
                throw new RuntimeException(e.toString());
            }
        }

        /**
         * Finish write and make device to boot into the it after reboot.
         *
         * @return {@code true} if the call succeeds. {@code false} if there is any native runtime
         *     error.
         */
        @RequiresPermission(android.Manifest.permission.MANAGE_DYNAMIC_SYSTEM)
        public boolean commit() {
            try {
                return mService.setEnable(true, true);
            } catch (RemoteException e) {
                throw new RuntimeException(e.toString());
            }
        }
    }
    /**
     * Start DynamicSystem installation.
     *
     * @return true if the call succeeds
     */
    @RequiresPermission(android.Manifest.permission.MANAGE_DYNAMIC_SYSTEM)
    public boolean startInstallation(String dsuSlot) {
        try {
            return mService.startInstallation(dsuSlot);
        } catch (RemoteException e) {
            throw new RuntimeException(e.toString());
        }
    }
    /**
     * Start DynamicSystem installation. This call may take an unbounded amount of time. The caller
     * may use another thread to call the getStartProgress() to get the progress.
     *
     * @param name The DSU partition name
     * @param size Size of the DSU image in bytes
     * @param readOnly True if the partition is read only, e.g. system.
     * @return {@code Integer} an IGsiService.INSTALL_* status code. {@link Session} an installation
     *     session object if successful, otherwise {@code null}.
     */
    @RequiresPermission(android.Manifest.permission.MANAGE_DYNAMIC_SYSTEM)
    public @NonNull Pair<Integer, Session> createPartition(
            String name, long size, boolean readOnly) {
        try {
            int status = mService.createPartition(name, size, readOnly);
            if (status == IGsiService.INSTALL_OK) {
                return new Pair<>(status, new Session());
            } else {
                return new Pair<>(status, null);
            }
        } catch (RemoteException e) {
            throw new RuntimeException(e.toString());
        }
    }
    /**
     * Complete the current partition installation.
     *
     * @return true if the partition installation completes without error.
     */
    @RequiresPermission(android.Manifest.permission.MANAGE_DYNAMIC_SYSTEM)
    public boolean closePartition() {
        try {
            return mService.closePartition();
        } catch (RemoteException e) {
            throw new RuntimeException(e.toString());
        }
    }
    /**
     * Finish a previously started installation. Installations without a cooresponding
     * finishInstallation() will be cleaned up during device boot.
     */
    @RequiresPermission(android.Manifest.permission.MANAGE_DYNAMIC_SYSTEM)
    public boolean finishInstallation() {
        try {
            return mService.finishInstallation();
        } catch (RemoteException e) {
            throw new RuntimeException(e.toString());
        }
    }
    /**
     * Query the progress of the current installation operation. This can be called while the
     * installation is in progress.
     *
     * @return GsiProgress GsiProgress { int status; long bytes_processed; long total_bytes; } The
     *     status field can be IGsiService.STATUS_NO_OPERATION, IGsiService.STATUS_WORKING or
     *     IGsiService.STATUS_COMPLETE.
     */
    @RequiresPermission(android.Manifest.permission.MANAGE_DYNAMIC_SYSTEM)
    public GsiProgress getInstallationProgress() {
        try {
            return mService.getInstallationProgress();
        } catch (RemoteException e) {
            throw new RuntimeException(e.toString());
        }
    }

    /**
     * Abort the installation process. Note this method must be called in a thread other than the
     * one calling the startInstallation method as the startInstallation method will not return
     * until it is finished.
     *
     * @return {@code true} if the call succeeds. {@code false} if there is no installation
     *     currently.
     */
    @RequiresPermission(android.Manifest.permission.MANAGE_DYNAMIC_SYSTEM)
    public boolean abort() {
        try {
            return mService.abort();
        } catch (RemoteException e) {
            throw new RuntimeException(e.toString());
        }
    }

    /** @return {@code true} if the device is running a dynamic system */
    @RequiresPermission(android.Manifest.permission.MANAGE_DYNAMIC_SYSTEM)
    public boolean isInUse() {
        try {
            return mService.isInUse();
        } catch (RemoteException e) {
            throw new RuntimeException(e.toString());
        }
    }

    /** @return {@code true} if the device has a dynamic system installed */
    @RequiresPermission(android.Manifest.permission.MANAGE_DYNAMIC_SYSTEM)
    public boolean isInstalled() {
        try {
            return mService.isInstalled();
        } catch (RemoteException e) {
            throw new RuntimeException(e.toString());
        }
    }

    /** @return {@code true} if the device has a dynamic system enabled */
    @RequiresPermission(android.Manifest.permission.MANAGE_DYNAMIC_SYSTEM)
    public boolean isEnabled() {
        try {
            return mService.isEnabled();
        } catch (RemoteException e) {
            throw new RuntimeException(e.toString());
        }
    }

    /**
     * Remove DynamicSystem installation if present
     *
     * @return {@code true} if the call succeeds. {@code false} if there is no installed image.
     */
    @RequiresPermission(android.Manifest.permission.MANAGE_DYNAMIC_SYSTEM)
    public boolean remove() {
        try {
            return mService.remove();
        } catch (RemoteException e) {
            throw new RuntimeException(e.toString());
        }
    }

    /**
     * Enable or disable DynamicSystem.
     * @return {@code true} if the call succeeds. {@code false} if there is no installed image.
     */
    @RequiresPermission(android.Manifest.permission.MANAGE_DYNAMIC_SYSTEM)
    public boolean setEnable(boolean enable, boolean oneShot) {
        try {
            return mService.setEnable(enable, oneShot);
        } catch (RemoteException e) {
            throw new RuntimeException(e.toString());
        }
    }

    /**
     * Returns the suggested scratch partition size for overlayFS.
     */
    @RequiresPermission(android.Manifest.permission.MANAGE_DYNAMIC_SYSTEM)
    public long suggestScratchSize() {
        try {
            return mService.suggestScratchSize();
        } catch (RemoteException e) {
            throw new RuntimeException(e.toString());
        }
    }
}