1/*
2 * Copyright (C) 2018 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package android.os;
18
19import static com.android.internal.util.Preconditions.checkNotNull;
20
21import android.annotation.RequiresPermission;
22import android.annotation.SystemApi;
23import android.annotation.SystemService;
24import android.content.Context;
25
26/**
27 * Allows querying and posting system update information.
28 *
29 * {@hide}
30 */
31@SystemApi
32@SystemService(Context.SYSTEM_UPDATE_SERVICE)
33public class SystemUpdateManager {
34    private static final String TAG = "SystemUpdateManager";
35
36    /** The status key of the system update info, expecting an int value. */
37    @SystemApi
38    public static final String KEY_STATUS = "status";
39
40    /** The title of the current update, expecting a String value. */
41    @SystemApi
42    public static final String KEY_TITLE = "title";
43
44    /** Whether it is a security update, expecting a boolean value. */
45    @SystemApi
46    public static final String KEY_IS_SECURITY_UPDATE = "is_security_update";
47
48    /** The build fingerprint after installing the current update, expecting a String value. */
49    @SystemApi
50    public static final String KEY_TARGET_BUILD_FINGERPRINT = "target_build_fingerprint";
51
52    /** The security patch level after installing the current update, expecting a String value. */
53    @SystemApi
54    public static final String KEY_TARGET_SECURITY_PATCH_LEVEL = "target_security_patch_level";
55
56    /**
57     * The KEY_STATUS value that indicates there's no update status info available.
58     */
59    @SystemApi
60    public static final int STATUS_UNKNOWN = 0;
61
62    /**
63     * The KEY_STATUS value that indicates there's no pending update.
64     */
65    @SystemApi
66    public static final int STATUS_IDLE = 1;
67
68    /**
69     * The KEY_STATUS value that indicates an update is available for download, but pending user
70     * approval to start.
71     */
72    @SystemApi
73    public static final int STATUS_WAITING_DOWNLOAD = 2;
74
75    /**
76     * The KEY_STATUS value that indicates an update is in progress (i.e. downloading or installing
77     * has started).
78     */
79    @SystemApi
80    public static final int STATUS_IN_PROGRESS = 3;
81
82    /**
83     * The KEY_STATUS value that indicates an update is available for install.
84     */
85    @SystemApi
86    public static final int STATUS_WAITING_INSTALL = 4;
87
88    /**
89     * The KEY_STATUS value that indicates an update will be installed after a reboot. This applies
90     * to both of A/B and non-A/B OTAs.
91     */
92    @SystemApi
93    public static final int STATUS_WAITING_REBOOT = 5;
94
95    private final ISystemUpdateManager mService;
96
97    /** @hide */
98    public SystemUpdateManager(ISystemUpdateManager service) {
99        mService = checkNotNull(service, "missing ISystemUpdateManager");
100    }
101
102    /**
103     * Queries the current pending system update info.
104     *
105     * <p>Requires the {@link android.Manifest.permission#READ_SYSTEM_UPDATE_INFO} or
106     * {@link android.Manifest.permission#RECOVERY} permission.
107     *
108     * @return A {@code Bundle} that contains the pending system update information in key-value
109     * pairs.
110     *
111     * @throws SecurityException if the caller is not allowed to read the info.
112     */
113    @SystemApi
114    @RequiresPermission(anyOf = {
115            android.Manifest.permission.READ_SYSTEM_UPDATE_INFO,
116            android.Manifest.permission.RECOVERY,
117    })
118    public Bundle retrieveSystemUpdateInfo() {
119        try {
120            return mService.retrieveSystemUpdateInfo();
121        } catch (RemoteException re) {
122            throw re.rethrowFromSystemServer();
123        }
124    }
125
126    /**
127     * Allows a system updater to publish the pending update info.
128     *
129     * <p>The reported info will not persist across reboots. Because only the reporting updater
130     * understands the criteria to determine a successful/failed update.
131     *
132     * <p>Requires the {@link android.Manifest.permission#RECOVERY} permission.
133     *
134     * @param infoBundle The {@code PersistableBundle} that contains the system update information,
135     * such as the current update status. {@link #KEY_STATUS} is required in the bundle.
136     *
137     * @throws IllegalArgumentException if @link #KEY_STATUS} does not exist.
138     * @throws SecurityException if the caller is not allowed to update the info.
139     */
140    @SystemApi
141    @RequiresPermission(android.Manifest.permission.RECOVERY)
142    public void updateSystemUpdateInfo(PersistableBundle infoBundle) {
143        if (infoBundle == null || !infoBundle.containsKey(KEY_STATUS)) {
144            throw new IllegalArgumentException("Missing status in the bundle");
145        }
146        try {
147            mService.updateSystemUpdateInfo(infoBundle);
148        } catch (RemoteException re) {
149            throw re.rethrowFromSystemServer();
150        }
151    }
152}
153