1 /*
2  * Copyright (C) 2014 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 
17 package android.service.persistentdata;
18 
19 import android.annotation.IntDef;
20 import android.annotation.NonNull;
21 import android.annotation.RequiresPermission;
22 import android.annotation.SuppressLint;
23 import android.annotation.SystemApi;
24 import android.annotation.SystemService;
25 import android.content.Context;
26 import android.os.RemoteException;
27 import android.service.oemlock.OemLockManager;
28 
29 import java.lang.annotation.Retention;
30 import java.lang.annotation.RetentionPolicy;
31 
32 /**
33  * Interface for reading and writing data blocks to a persistent partition.
34  *
35  * Allows writing one block at a time. Namely, each time
36  * {@link PersistentDataBlockManager#write(byte[])}
37  * is called, it will overwite the data that was previously written on the block.
38  *
39  * Clients can query the size of the currently written block via
40  * {@link PersistentDataBlockManager#getDataBlockSize()}.
41  *
42  * Clients can query the maximum size for a block via
43  * {@link PersistentDataBlockManager#getMaximumDataBlockSize()}
44  *
45  * Clients can read the currently written block by invoking
46  * {@link PersistentDataBlockManager#read()}.
47  *
48  * @hide
49  */
50 @SystemApi
51 @SystemService(Context.PERSISTENT_DATA_BLOCK_SERVICE)
52 public class PersistentDataBlockManager {
53     private static final String TAG = PersistentDataBlockManager.class.getSimpleName();
54     private IPersistentDataBlockService sService;
55 
56     /**
57      * Indicates that the device's bootloader lock state is UNKNOWN.
58      */
59     public static final int FLASH_LOCK_UNKNOWN = -1;
60     /**
61      * Indicates that the device's bootloader is UNLOCKED.
62      */
63     public static final int FLASH_LOCK_UNLOCKED = 0;
64     /**
65      * Indicates that the device's bootloader is LOCKED.
66      */
67     public static final int FLASH_LOCK_LOCKED = 1;
68 
69     @IntDef(prefix = { "FLASH_LOCK_" }, value = {
70             FLASH_LOCK_UNKNOWN,
71             FLASH_LOCK_LOCKED,
72             FLASH_LOCK_UNLOCKED,
73     })
74     @Retention(RetentionPolicy.SOURCE)
75     public @interface FlashLockState {}
76 
77     /** @hide */
PersistentDataBlockManager(IPersistentDataBlockService service)78     public PersistentDataBlockManager(IPersistentDataBlockService service) {
79         sService = service;
80     }
81 
82     /**
83      * Writes {@code data} to the persistent partition. Previously written data
84      * will be overwritten. This data will persist across factory resets.
85      *
86      * Returns the number of bytes written or -1 on error. If the block is too big
87      * to fit on the partition, returns -MAX_BLOCK_SIZE.
88      *
89      * {@link #wipe} will block any further {@link #write} operation until reboot,
90      * in which case -1 will be returned.
91      *
92      * @param data the data to write
93      */
94     @SuppressLint("RequiresPermission")
write(byte[] data)95     public int write(byte[] data) {
96         try {
97             return sService.write(data);
98         } catch (RemoteException e) {
99             throw e.rethrowFromSystemServer();
100         }
101     }
102 
103     /**
104      * Returns the data block stored on the persistent partition.
105      */
106     @SuppressLint("RequiresPermission")
read()107     public byte[] read() {
108         try {
109             return sService.read();
110         } catch (RemoteException e) {
111             throw e.rethrowFromSystemServer();
112         }
113     }
114 
115     /**
116      * Retrieves the size of the block currently written to the persistent partition.
117      *
118      * Return -1 on error.
119      */
120     @RequiresPermission(android.Manifest.permission.ACCESS_PDB_STATE)
getDataBlockSize()121     public int getDataBlockSize() {
122         try {
123             return sService.getDataBlockSize();
124         } catch (RemoteException e) {
125             throw e.rethrowFromSystemServer();
126         }
127     }
128 
129     /**
130      * Retrieves the maximum size allowed for a data block.
131      *
132      * Returns -1 on error.
133      */
134     @SuppressLint("RequiresPermission")
getMaximumDataBlockSize()135     public long getMaximumDataBlockSize() {
136         try {
137             return sService.getMaximumDataBlockSize();
138         } catch (RemoteException e) {
139             throw e.rethrowFromSystemServer();
140         }
141     }
142 
143     /**
144      * Zeroes the previously written block in its entirety. Calling this method
145      * will erase all data written to the persistent data partition.
146      * It will also prevent any further {@link #write} operation until reboot,
147      * in order to prevent a potential race condition. See b/30352311.
148      */
149     @RequiresPermission(android.Manifest.permission.OEM_UNLOCK_STATE)
wipe()150     public void wipe() {
151         try {
152             sService.wipe();
153         } catch (RemoteException e) {
154             throw e.rethrowFromSystemServer();
155         }
156     }
157 
158     /**
159      * Writes a byte enabling or disabling the ability to "OEM unlock" the device.
160      *
161      * @deprecated use {@link OemLockManager#setOemUnlockAllowedByUser(boolean)} instead.
162      */
163     @RequiresPermission(android.Manifest.permission.OEM_UNLOCK_STATE)
setOemUnlockEnabled(boolean enabled)164     public void setOemUnlockEnabled(boolean enabled) {
165         try {
166             sService.setOemUnlockEnabled(enabled);
167         } catch (RemoteException e) {
168             throw e.rethrowFromSystemServer();
169         }
170     }
171 
172     /**
173      * Returns whether or not "OEM unlock" is enabled or disabled on this device.
174      *
175      * @deprecated use {@link OemLockManager#isOemUnlockAllowedByUser()} instead.
176      */
177     @RequiresPermission(anyOf = {
178             android.Manifest.permission.READ_OEM_UNLOCK_STATE,
179             android.Manifest.permission.OEM_UNLOCK_STATE
180     })
getOemUnlockEnabled()181     public boolean getOemUnlockEnabled() {
182         try {
183             return sService.getOemUnlockEnabled();
184         } catch (RemoteException e) {
185             throw e.rethrowFromSystemServer();
186         }
187     }
188 
189     /**
190      * Retrieves available information about this device's flash lock state.
191      *
192      * @return {@link #FLASH_LOCK_LOCKED} if device bootloader is locked,
193      * {@link #FLASH_LOCK_UNLOCKED} if device bootloader is unlocked, or {@link #FLASH_LOCK_UNKNOWN}
194      * if this information cannot be ascertained on this device.
195      */
196     @RequiresPermission(anyOf = {
197             android.Manifest.permission.READ_OEM_UNLOCK_STATE,
198             android.Manifest.permission.OEM_UNLOCK_STATE
199     })
200     @FlashLockState
getFlashLockState()201     public int getFlashLockState() {
202         try {
203             return sService.getFlashLockState();
204         } catch (RemoteException e) {
205             throw e.rethrowFromSystemServer();
206         }
207     }
208 
209     /**
210      * Returns the package name which can access the persistent data partition.
211      *
212      * @hide
213      */
214     @SystemApi
215     @NonNull
216     @RequiresPermission(android.Manifest.permission.ACCESS_PDB_STATE)
getPersistentDataPackageName()217     public String getPersistentDataPackageName() {
218         try {
219             return sService.getPersistentDataPackageName();
220         } catch (RemoteException e) {
221             throw e.rethrowFromSystemServer();
222         }
223     }
224 }
225