PersistentDataBlockManager.java revision 66445a639dc134d09393f5069b7683ec36d4cd07
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
17package android.service.persistentdata;
18
19import android.annotation.SystemApi;
20import android.app.PendingIntent;
21import android.os.Bundle;
22import android.os.RemoteException;
23import android.util.Slog;
24
25/**
26 * Interface for reading and writing data blocks to a persistent partition.
27 *
28 * Allows writing one block at a time. Namely, each time
29 * {@link PersistentDataBlockManager#write(byte[])}
30 * is called, it will overwite the data that was previously written on the block.
31 *
32 * Clients can query the size of the currently written block via
33 * {@link PersistentDataBlockManager#getDataBlockSize()}.
34 *
35 * Clients can query the maximum size for a block via
36 * {@link PersistentDataBlockManager#getMaximumDataBlockSize()}
37 *
38 * Clients can read the currently written block by invoking
39 * {@link PersistentDataBlockManager#read()}.
40 *
41 * @hide
42 */
43@SystemApi
44public class PersistentDataBlockManager {
45    private static final String TAG = PersistentDataBlockManager.class.getSimpleName();
46
47    /**
48     * Broadcast action that will be called when the {@link #wipeIfAllowed(Bundle,PendingIntent)}
49     * method is called.  A broadcast with this action will be sent to the package allowed to write
50     * to the persistent data block. Packages receiving this broadcasts should respond by using the
51     * {@link android.app.PendingIntent} sent in the {@link #EXTRA_WIPE_IF_ALLOWED_CALLBACK} extra.
52     */
53    public static final String ACTION_WIPE_IF_ALLOWED
54            = "android.service.persistentdata.action.WIPE_IF_ALLOWED";
55
56    /**
57     * A {@link android.os.Parcelable} extra of type {@link android.app.PendingIntent} used to
58     * response to {@link #wipeIfAllowed(Bundle,PendingIntent)}. This extra will set in broadcasts
59     * with an action of {@link #ACTION_WIPE_IF_ALLOWED}.
60     */
61    public static final String EXTRA_WIPE_IF_ALLOWED_CALLBACK
62            = "android.service.persistentdata.extra.WIPE_IF_ALLOWED_CALLBACK";
63
64    /**
65     * Result code indicating that the data block was wiped.
66     *
67     * <p>This value is set as result code of the {@link android.app.PendingIntent} argument to
68     * {@link #wipeIfAllowed(Bundle,PendingIntent)}
69     */
70    public static final int STATUS_SUCCESS = 0;
71
72    /**
73     * Result code indicating that a remote exception was received while processing the request.
74     *
75     * <p>This value is set as result code of the {@link android.app.PendingIntent} argument to
76     * {@link #wipeIfAllowed(Bundle,PendingIntent)}
77     */
78    public static final int STATUS_ERROR_REMOTE_EXCEPTION = 1;
79
80    /**
81     * Result code indicating that a network error occurred while processing the request.
82     *
83     * <p>This value is set as result code of the {@link android.app.PendingIntent} argument to
84     * {@link #wipeIfAllowed(Bundle,PendingIntent)}
85     */
86    public static final int STATUS_ERROR_NETWORK_ERROR = 2;
87
88    /**
89     * Result code indicating that the data block could not be cleared with the provided data.
90     *
91     * <p>This value is set as result code of the {@link android.app.PendingIntent} argument to
92     * {@link #wipeIfAllowed(Bundle,PendingIntent)}
93     */
94    public static final int STATUS_ERROR_NOT_COMPLIANT = 3;
95
96    private IPersistentDataBlockService sService;
97
98    public PersistentDataBlockManager(IPersistentDataBlockService service) {
99        sService = service;
100    }
101
102    /**
103     * Writes {@code data} to the persistent partition. Previously written data
104     * will be overwritten. This data will persist across factory resets.
105     *
106     * Returns the number of bytes written or -1 on error. If the block is too big
107     * to fit on the partition, returns -MAX_BLOCK_SIZE.
108     *
109     * @param data the data to write
110     */
111    public int write(byte[] data) {
112        try {
113            return sService.write(data);
114        } catch (RemoteException e) {
115            onError("writing data");
116            return -1;
117        }
118    }
119
120    /**
121     * Returns the data block stored on the persistent partition.
122     */
123    public byte[] read() {
124        try {
125            return sService.read();
126        } catch (RemoteException e) {
127            onError("reading data");
128            return null;
129        }
130    }
131
132    /**
133     * Retrieves the size of the block currently written to the persistent partition.
134     *
135     * Return -1 on error.
136     */
137    public int getDataBlockSize() {
138        try {
139            return sService.getDataBlockSize();
140        } catch (RemoteException e) {
141            onError("getting data block size");
142            return -1;
143        }
144    }
145
146    /**
147     * Retrieves the maximum size allowed for a data block.
148     *
149     * Returns -1 on error.
150     */
151    public long getMaximumDataBlockSize() {
152        try {
153            return sService.getMaximumDataBlockSize();
154        } catch (RemoteException e) {
155            onError("getting maximum data block size");
156            return -1;
157        }
158    }
159
160    /**
161     * Zeroes the previously written block in its entirety. Calling this method
162     * will erase all data written to the persistent data partition.
163     */
164    public void wipe() {
165        try {
166            sService.wipe();
167        } catch (RemoteException e) {
168            onError("wiping persistent partition");
169        }
170    }
171
172    /**
173     * Attempt to wipe the data block by sending a broadcast to the package allowed to modify the
174     * datablock. The allowed package can refuse to wipe the data block based on the contents of
175     * the specified bundle. This bundle may contain data used by the allowed package to wipe the
176     * partition such as account credentials or an authorization token.
177     * @param bundle data used to wipe the data block. The contents of this bundle depend on the
178     *    allowed package receiving the data.
179     * @param pi intent called when attempt finished. The result code of this intent will be set
180     *    to one of {@link #STATUS_SUCCESS}, {@link #STATUS_ERROR_REMOTE_EXCEPTION},
181     *    {@link #STATUS_ERROR_NETWORK_ERROR}, or {@link #STATUS_ERROR_NOT_COMPLIANT}.
182     */
183    public void wipeIfAllowed(Bundle bundle, PendingIntent pi) {
184        if (pi == null) {
185            throw new NullPointerException();
186        }
187        try {
188            sService.wipeIfAllowed(bundle, pi);
189        } catch (RemoteException e) {
190            onError("wiping persistent partition");
191        }
192    }
193
194    /**
195     * Writes a byte enabling or disabling the ability to "OEM unlock" the device.
196     */
197    public void setOemUnlockEnabled(boolean enabled) {
198        try {
199            sService.setOemUnlockEnabled(enabled);
200        } catch (RemoteException e) {
201            onError("setting OEM unlock enabled to " + enabled);
202        }
203    }
204
205    /**
206     * Returns whether or not "OEM unlock" is enabled or disabled on this device.
207     */
208    public boolean getOemUnlockEnabled() {
209        try {
210            return sService.getOemUnlockEnabled();
211        } catch (RemoteException e) {
212            onError("getting OEM unlock enabled bit");
213            return false;
214        }
215    }
216
217    private void onError(String msg) {
218        Slog.v(TAG, "Remote exception while " + msg);
219    }
220}
221