blob: 79cd1b17a5b52f13879af7841b55c2dea324d473 [file] [log] [blame]
Sudheer Shankaab1d4162020-01-07 10:37:50 -08001/*
2 * Copyright 2020 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 */
16package com.android.server.blob;
17
Sudheer Shanka364364b2020-02-19 17:56:09 -080018import static android.provider.DeviceConfig.NAMESPACE_BLOBSTORE;
19import static android.text.format.Formatter.FLAG_IEC_UNITS;
20import static android.text.format.Formatter.formatFileSize;
Sudheer Shanka364364b2020-02-19 17:56:09 -080021
Sudheer Shankaab1d4162020-01-07 10:37:50 -080022import android.annotation.NonNull;
23import android.annotation.Nullable;
Sudheer Shanka364364b2020-02-19 17:56:09 -080024import android.content.Context;
Sudheer Shankaab1d4162020-01-07 10:37:50 -080025import android.os.Environment;
Sudheer Shanka364364b2020-02-19 17:56:09 -080026import android.provider.DeviceConfig;
27import android.provider.DeviceConfig.Properties;
28import android.util.DataUnit;
Sudheer Shankae53e1ed2020-02-03 17:15:24 -080029import android.util.Log;
Sudheer Shankaab1d4162020-01-07 10:37:50 -080030import android.util.Slog;
Sudheer Shankac0fd5fa2020-03-15 23:31:37 -070031import android.util.TimeUtils;
Sudheer Shankaab1d4162020-01-07 10:37:50 -080032
Sudheer Shanka364364b2020-02-19 17:56:09 -080033import com.android.internal.util.IndentingPrintWriter;
34
Sudheer Shankaab1d4162020-01-07 10:37:50 -080035import java.io.File;
Sudheer Shankaae53d112020-01-31 14:20:53 -080036import java.util.concurrent.TimeUnit;
Sudheer Shankaab1d4162020-01-07 10:37:50 -080037
38class BlobStoreConfig {
39 public static final String TAG = "BlobStore";
Sudheer Shankae53e1ed2020-02-03 17:15:24 -080040 public static final boolean LOGV = Log.isLoggable(TAG, Log.VERBOSE);
Sudheer Shankaab1d4162020-01-07 10:37:50 -080041
Sudheer Shanka1406bc82020-02-03 12:27:24 -080042 // Initial version.
43 public static final int XML_VERSION_INIT = 1;
44 // Added a string variant of lease description.
45 public static final int XML_VERSION_ADD_STRING_DESC = 2;
Sudheer Shanka1b6b8252020-03-04 22:19:21 -080046 public static final int XML_VERSION_ADD_DESC_RES_NAME = 3;
Sudheer Shankaaf3f8872020-03-24 11:26:23 -070047 public static final int XML_VERSION_ADD_COMMIT_TIME = 4;
Sudheer Shankab2a17b72020-05-28 01:14:10 -070048 public static final int XML_VERSION_ADD_SESSION_CREATION_TIME = 5;
Sudheer Shanka1406bc82020-02-03 12:27:24 -080049
Sudheer Shankab2a17b72020-05-28 01:14:10 -070050 public static final int XML_VERSION_CURRENT = XML_VERSION_ADD_SESSION_CREATION_TIME;
Sudheer Shankaf6e23b92020-01-15 01:51:15 -080051
Michael Wachenschwanz1a7f7ab2020-06-09 20:16:27 -070052 public static final long INVALID_BLOB_ID = 0;
53 public static final long INVALID_BLOB_SIZE = 0;
54
Sudheer Shanka9f2296a2020-01-25 23:22:34 -080055 private static final String ROOT_DIR_NAME = "blobstore";
56 private static final String BLOBS_DIR_NAME = "blobs";
57 private static final String SESSIONS_INDEX_FILE_NAME = "sessions_index.xml";
58 private static final String BLOBS_INDEX_FILE_NAME = "blobs_index.xml";
59
Sudheer Shankaae53d112020-01-31 14:20:53 -080060 /**
61 * Job Id for idle maintenance job ({@link BlobStoreIdleJobService}).
62 */
63 public static final int IDLE_JOB_ID = 0xB70B1D7; // 191934935L
Sudheer Shankaae53d112020-01-31 14:20:53 -080064
Sudheer Shanka364364b2020-02-19 17:56:09 -080065 public static class DeviceConfigProperties {
66 /**
Sudheer Shanka90ac4a62020-05-25 15:40:21 -070067 * Denotes the max time period (in millis) between each idle maintenance job run.
68 */
69 public static final String KEY_IDLE_JOB_PERIOD_MS = "idle_job_period_ms";
70 public static final long DEFAULT_IDLE_JOB_PERIOD_MS = TimeUnit.DAYS.toMillis(1);
71 public static long IDLE_JOB_PERIOD_MS = DEFAULT_IDLE_JOB_PERIOD_MS;
72
73 /**
74 * Denotes the timeout in millis after which sessions with no updates will be deleted.
75 */
76 public static final String KEY_SESSION_EXPIRY_TIMEOUT_MS =
77 "session_expiry_timeout_ms";
78 public static final long DEFAULT_SESSION_EXPIRY_TIMEOUT_MS = TimeUnit.DAYS.toMillis(7);
79 public static long SESSION_EXPIRY_TIMEOUT_MS = DEFAULT_SESSION_EXPIRY_TIMEOUT_MS;
80
81 /**
Sudheer Shanka364364b2020-02-19 17:56:09 -080082 * Denotes how low the limit for the amount of data, that an app will be allowed to acquire
83 * a lease on, can be.
84 */
85 public static final String KEY_TOTAL_BYTES_PER_APP_LIMIT_FLOOR =
86 "total_bytes_per_app_limit_floor";
87 public static final long DEFAULT_TOTAL_BYTES_PER_APP_LIMIT_FLOOR =
88 DataUnit.MEBIBYTES.toBytes(300); // 300 MiB
89 public static long TOTAL_BYTES_PER_APP_LIMIT_FLOOR =
90 DEFAULT_TOTAL_BYTES_PER_APP_LIMIT_FLOOR;
91
92 /**
93 * Denotes the maximum amount of data an app can acquire a lease on, in terms of fraction
94 * of total disk space.
95 */
96 public static final String KEY_TOTAL_BYTES_PER_APP_LIMIT_FRACTION =
97 "total_bytes_per_app_limit_fraction";
98 public static final float DEFAULT_TOTAL_BYTES_PER_APP_LIMIT_FRACTION = 0.01f;
99 public static float TOTAL_BYTES_PER_APP_LIMIT_FRACTION =
100 DEFAULT_TOTAL_BYTES_PER_APP_LIMIT_FRACTION;
101
Sudheer Shankac0fd5fa2020-03-15 23:31:37 -0700102 /**
103 * Denotes the duration from the time a blob is committed that we wait for a lease to
104 * be acquired before deciding to delete the blob for having no leases.
105 */
106 public static final String KEY_LEASE_ACQUISITION_WAIT_DURATION_MS =
107 "lease_acquisition_wait_time_ms";
108 public static final long DEFAULT_LEASE_ACQUISITION_WAIT_DURATION_MS =
109 TimeUnit.HOURS.toMillis(6);
110 public static long LEASE_ACQUISITION_WAIT_DURATION_MS =
111 DEFAULT_LEASE_ACQUISITION_WAIT_DURATION_MS;
112
Sudheer Shankaaf3f8872020-03-24 11:26:23 -0700113 /**
114 * Denotes the duration from the time a blob is committed that any new commits of the same
115 * data blob from the same committer will be treated as if they occurred at the earlier
116 * commit time.
117 */
118 public static final String KEY_COMMIT_COOL_OFF_DURATION_MS =
119 "commit_cool_off_duration_ms";
120 public static final long DEFAULT_COMMIT_COOL_OFF_DURATION_MS =
121 TimeUnit.HOURS.toMillis(48);
122 public static long COMMIT_COOL_OFF_DURATION_MS =
123 DEFAULT_COMMIT_COOL_OFF_DURATION_MS;
124
Sudheer Shankad6f47942020-06-18 16:46:36 -0700125 /**
126 * Denotes whether to use RevocableFileDescriptor when apps try to read session/blob data.
127 */
128 public static final String KEY_USE_REVOCABLE_FD_FOR_READS =
129 "use_revocable_fd_for_reads";
130 public static final boolean DEFAULT_USE_REVOCABLE_FD_FOR_READS = true;
131 public static boolean USE_REVOCABLE_FD_FOR_READS =
132 DEFAULT_USE_REVOCABLE_FD_FOR_READS;
133
Sudheer Shankafbda8d72020-06-17 05:01:38 -0700134 /**
135 * Denotes how long before a blob is deleted, once the last lease on it is released.
136 */
137 public static final String KEY_DELETE_ON_LAST_LEASE_DELAY_MS =
138 "delete_on_last_lease_delay_ms";
139 public static final long DEFAULT_DELETE_ON_LAST_LEASE_DELAY_MS =
140 TimeUnit.HOURS.toMillis(6);
141 public static long DELETE_ON_LAST_LEASE_DELAY_MS =
142 DEFAULT_DELETE_ON_LAST_LEASE_DELAY_MS;
143
Sudheer Shanka07717c92020-06-23 14:06:47 -0700144 /**
145 * Denotes the maximum number of active sessions per app at any time.
146 */
147 public static final String KEY_MAX_ACTIVE_SESSIONS = "max_active_sessions";
148 public static int DEFAULT_MAX_ACTIVE_SESSIONS = 250;
149 public static int MAX_ACTIVE_SESSIONS = DEFAULT_MAX_ACTIVE_SESSIONS;
150
151 /**
152 * Denotes the maximum number of committed blobs per app at any time.
153 */
154 public static final String KEY_MAX_COMMITTED_BLOBS = "max_committed_blobs";
155 public static int DEFAULT_MAX_COMMITTED_BLOBS = 1000;
156 public static int MAX_COMMITTED_BLOBS = DEFAULT_MAX_COMMITTED_BLOBS;
157
158 /**
159 * Denotes the maximum number of leased blobs per app at any time.
160 */
161 public static final String KEY_MAX_LEASED_BLOBS = "max_leased_blobs";
162 public static int DEFAULT_MAX_LEASED_BLOBS = 500;
163 public static int MAX_LEASED_BLOBS = DEFAULT_MAX_LEASED_BLOBS;
164
165 /**
166 * Denotes the maximum number of packages explicitly permitted to access a blob
167 * (permitted as part of creating a {@link BlobAccessMode}).
168 */
169 public static final String KEY_MAX_BLOB_ACCESS_PERMITTED_PACKAGES = "max_permitted_pks";
170 public static int DEFAULT_MAX_BLOB_ACCESS_PERMITTED_PACKAGES = 300;
171 public static int MAX_BLOB_ACCESS_PERMITTED_PACKAGES =
172 DEFAULT_MAX_BLOB_ACCESS_PERMITTED_PACKAGES;
173
Sudheer Shanka364364b2020-02-19 17:56:09 -0800174 static void refresh(Properties properties) {
175 if (!NAMESPACE_BLOBSTORE.equals(properties.getNamespace())) {
176 return;
177 }
178 properties.getKeyset().forEach(key -> {
179 switch (key) {
Sudheer Shanka90ac4a62020-05-25 15:40:21 -0700180 case KEY_IDLE_JOB_PERIOD_MS:
181 IDLE_JOB_PERIOD_MS = properties.getLong(key, DEFAULT_IDLE_JOB_PERIOD_MS);
182 break;
183 case KEY_SESSION_EXPIRY_TIMEOUT_MS:
184 SESSION_EXPIRY_TIMEOUT_MS = properties.getLong(key,
185 DEFAULT_SESSION_EXPIRY_TIMEOUT_MS);
186 break;
Sudheer Shanka364364b2020-02-19 17:56:09 -0800187 case KEY_TOTAL_BYTES_PER_APP_LIMIT_FLOOR:
188 TOTAL_BYTES_PER_APP_LIMIT_FLOOR = properties.getLong(key,
189 DEFAULT_TOTAL_BYTES_PER_APP_LIMIT_FLOOR);
190 break;
191 case KEY_TOTAL_BYTES_PER_APP_LIMIT_FRACTION:
192 TOTAL_BYTES_PER_APP_LIMIT_FRACTION = properties.getFloat(key,
193 DEFAULT_TOTAL_BYTES_PER_APP_LIMIT_FRACTION);
194 break;
Sudheer Shankac0fd5fa2020-03-15 23:31:37 -0700195 case KEY_LEASE_ACQUISITION_WAIT_DURATION_MS:
196 LEASE_ACQUISITION_WAIT_DURATION_MS = properties.getLong(key,
197 DEFAULT_LEASE_ACQUISITION_WAIT_DURATION_MS);
198 break;
Sudheer Shanka13d78642020-04-22 03:56:38 -0700199 case KEY_COMMIT_COOL_OFF_DURATION_MS:
200 COMMIT_COOL_OFF_DURATION_MS = properties.getLong(key,
201 DEFAULT_COMMIT_COOL_OFF_DURATION_MS);
202 break;
Sudheer Shankad6f47942020-06-18 16:46:36 -0700203 case KEY_USE_REVOCABLE_FD_FOR_READS:
204 USE_REVOCABLE_FD_FOR_READS = properties.getBoolean(key,
205 DEFAULT_USE_REVOCABLE_FD_FOR_READS);
206 break;
Sudheer Shankafbda8d72020-06-17 05:01:38 -0700207 case KEY_DELETE_ON_LAST_LEASE_DELAY_MS:
208 DELETE_ON_LAST_LEASE_DELAY_MS = properties.getLong(key,
209 DEFAULT_DELETE_ON_LAST_LEASE_DELAY_MS);
210 break;
Sudheer Shanka07717c92020-06-23 14:06:47 -0700211 case KEY_MAX_ACTIVE_SESSIONS:
212 MAX_ACTIVE_SESSIONS = properties.getInt(key, DEFAULT_MAX_ACTIVE_SESSIONS);
213 break;
214 case KEY_MAX_COMMITTED_BLOBS:
215 MAX_COMMITTED_BLOBS = properties.getInt(key, DEFAULT_MAX_COMMITTED_BLOBS);
216 break;
217 case KEY_MAX_LEASED_BLOBS:
218 MAX_LEASED_BLOBS = properties.getInt(key, DEFAULT_MAX_LEASED_BLOBS);
219 break;
220 case KEY_MAX_BLOB_ACCESS_PERMITTED_PACKAGES:
221 MAX_BLOB_ACCESS_PERMITTED_PACKAGES = properties.getInt(key,
222 DEFAULT_MAX_BLOB_ACCESS_PERMITTED_PACKAGES);
223 break;
Sudheer Shanka364364b2020-02-19 17:56:09 -0800224 default:
225 Slog.wtf(TAG, "Unknown key in device config properties: " + key);
226 }
227 });
228 }
229
230 static void dump(IndentingPrintWriter fout, Context context) {
231 final String dumpFormat = "%s: [cur: %s, def: %s]";
Sudheer Shanka90ac4a62020-05-25 15:40:21 -0700232 fout.println(String.format(dumpFormat, KEY_IDLE_JOB_PERIOD_MS,
233 TimeUtils.formatDuration(IDLE_JOB_PERIOD_MS),
234 TimeUtils.formatDuration(DEFAULT_IDLE_JOB_PERIOD_MS)));
235 fout.println(String.format(dumpFormat, KEY_SESSION_EXPIRY_TIMEOUT_MS,
236 TimeUtils.formatDuration(SESSION_EXPIRY_TIMEOUT_MS),
237 TimeUtils.formatDuration(DEFAULT_SESSION_EXPIRY_TIMEOUT_MS)));
Sudheer Shanka364364b2020-02-19 17:56:09 -0800238 fout.println(String.format(dumpFormat, KEY_TOTAL_BYTES_PER_APP_LIMIT_FLOOR,
239 formatFileSize(context, TOTAL_BYTES_PER_APP_LIMIT_FLOOR, FLAG_IEC_UNITS),
240 formatFileSize(context, DEFAULT_TOTAL_BYTES_PER_APP_LIMIT_FLOOR,
241 FLAG_IEC_UNITS)));
242 fout.println(String.format(dumpFormat, KEY_TOTAL_BYTES_PER_APP_LIMIT_FRACTION,
243 TOTAL_BYTES_PER_APP_LIMIT_FRACTION,
244 DEFAULT_TOTAL_BYTES_PER_APP_LIMIT_FRACTION));
Sudheer Shankac0fd5fa2020-03-15 23:31:37 -0700245 fout.println(String.format(dumpFormat, KEY_LEASE_ACQUISITION_WAIT_DURATION_MS,
246 TimeUtils.formatDuration(LEASE_ACQUISITION_WAIT_DURATION_MS),
247 TimeUtils.formatDuration(DEFAULT_LEASE_ACQUISITION_WAIT_DURATION_MS)));
Sudheer Shanka13d78642020-04-22 03:56:38 -0700248 fout.println(String.format(dumpFormat, KEY_COMMIT_COOL_OFF_DURATION_MS,
249 TimeUtils.formatDuration(COMMIT_COOL_OFF_DURATION_MS),
250 TimeUtils.formatDuration(DEFAULT_COMMIT_COOL_OFF_DURATION_MS)));
Sudheer Shankad6f47942020-06-18 16:46:36 -0700251 fout.println(String.format(dumpFormat, KEY_USE_REVOCABLE_FD_FOR_READS,
252 USE_REVOCABLE_FD_FOR_READS, DEFAULT_USE_REVOCABLE_FD_FOR_READS));
Sudheer Shankafbda8d72020-06-17 05:01:38 -0700253 fout.println(String.format(dumpFormat, KEY_DELETE_ON_LAST_LEASE_DELAY_MS,
254 TimeUtils.formatDuration(DELETE_ON_LAST_LEASE_DELAY_MS),
255 TimeUtils.formatDuration(DEFAULT_DELETE_ON_LAST_LEASE_DELAY_MS)));
Sudheer Shanka07717c92020-06-23 14:06:47 -0700256 fout.println(String.format(dumpFormat, KEY_MAX_ACTIVE_SESSIONS,
257 MAX_ACTIVE_SESSIONS, DEFAULT_MAX_ACTIVE_SESSIONS));
258 fout.println(String.format(dumpFormat, KEY_MAX_COMMITTED_BLOBS,
259 MAX_COMMITTED_BLOBS, DEFAULT_MAX_COMMITTED_BLOBS));
260 fout.println(String.format(dumpFormat, KEY_MAX_LEASED_BLOBS,
261 MAX_LEASED_BLOBS, DEFAULT_MAX_LEASED_BLOBS));
262 fout.println(String.format(dumpFormat, KEY_MAX_BLOB_ACCESS_PERMITTED_PACKAGES,
263 MAX_BLOB_ACCESS_PERMITTED_PACKAGES,
264 DEFAULT_MAX_BLOB_ACCESS_PERMITTED_PACKAGES));
Sudheer Shanka364364b2020-02-19 17:56:09 -0800265 }
266 }
267
268 public static void initialize(Context context) {
269 DeviceConfig.addOnPropertiesChangedListener(NAMESPACE_BLOBSTORE,
270 context.getMainExecutor(),
271 properties -> DeviceConfigProperties.refresh(properties));
272 DeviceConfigProperties.refresh(DeviceConfig.getProperties(NAMESPACE_BLOBSTORE));
273 }
274
275 /**
Sudheer Shanka90ac4a62020-05-25 15:40:21 -0700276 * Returns the max time period (in millis) between each idle maintenance job run.
277 */
278 public static long getIdleJobPeriodMs() {
279 return DeviceConfigProperties.IDLE_JOB_PERIOD_MS;
280 }
281
282 /**
283 * Returns whether a session is expired or not. A session is considered expired if the session
284 * has not been modified in a while (i.e. SESSION_EXPIRY_TIMEOUT_MS).
285 */
286 public static boolean hasSessionExpired(long sessionLastModifiedMs) {
287 return sessionLastModifiedMs
288 < System.currentTimeMillis() - DeviceConfigProperties.SESSION_EXPIRY_TIMEOUT_MS;
289 }
290
291 /**
Sudheer Shanka364364b2020-02-19 17:56:09 -0800292 * Returns the maximum amount of data that an app can acquire a lease on.
293 */
294 public static long getAppDataBytesLimit() {
295 final long totalBytesLimit = (long) (Environment.getDataSystemDirectory().getTotalSpace()
296 * DeviceConfigProperties.TOTAL_BYTES_PER_APP_LIMIT_FRACTION);
297 return Math.max(DeviceConfigProperties.TOTAL_BYTES_PER_APP_LIMIT_FLOOR, totalBytesLimit);
298 }
299
Sudheer Shankac0fd5fa2020-03-15 23:31:37 -0700300 /**
301 * Returns whether the wait time for lease acquisition for a blob has elapsed.
302 */
303 public static boolean hasLeaseWaitTimeElapsed(long commitTimeMs) {
304 return commitTimeMs + DeviceConfigProperties.LEASE_ACQUISITION_WAIT_DURATION_MS
305 < System.currentTimeMillis();
306 }
307
Sudheer Shankaaf3f8872020-03-24 11:26:23 -0700308 /**
309 * Returns an adjusted commit time depending on whether commit cool-off period has elapsed.
310 *
311 * If this is the initial commit or the earlier commit cool-off period has elapsed, then
312 * the new commit time is used. Otherwise, the earlier commit time is used.
313 */
314 public static long getAdjustedCommitTimeMs(long oldCommitTimeMs, long newCommitTimeMs) {
315 if (oldCommitTimeMs == 0 || hasCommitCoolOffPeriodElapsed(oldCommitTimeMs)) {
316 return newCommitTimeMs;
317 }
318 return oldCommitTimeMs;
319 }
320
321 /**
322 * Returns whether the commit cool-off period has elapsed.
323 */
324 private static boolean hasCommitCoolOffPeriodElapsed(long commitTimeMs) {
325 return commitTimeMs + DeviceConfigProperties.COMMIT_COOL_OFF_DURATION_MS
326 < System.currentTimeMillis();
327 }
328
Sudheer Shankad6f47942020-06-18 16:46:36 -0700329 /**
330 * Return whether to use RevocableFileDescriptor when apps try to read session/blob data.
331 */
332 public static boolean shouldUseRevocableFdForReads() {
333 return DeviceConfigProperties.USE_REVOCABLE_FD_FOR_READS;
334 }
335
Sudheer Shankafbda8d72020-06-17 05:01:38 -0700336 /**
337 * Returns the duration to wait before a blob is deleted, once the last lease on it is released.
338 */
339 public static long getDeletionOnLastLeaseDelayMs() {
340 return DeviceConfigProperties.DELETE_ON_LAST_LEASE_DELAY_MS;
341 }
342
Sudheer Shanka07717c92020-06-23 14:06:47 -0700343 /**
344 * Returns the maximum number of active sessions per app.
345 */
346 public static int getMaxActiveSessions() {
347 return DeviceConfigProperties.MAX_ACTIVE_SESSIONS;
348 }
349
350 /**
351 * Returns the maximum number of committed blobs per app.
352 */
353 public static int getMaxCommittedBlobs() {
354 return DeviceConfigProperties.MAX_COMMITTED_BLOBS;
355 }
356
357 /**
358 * Returns the maximum number of leased blobs per app.
359 */
360 public static int getMaxLeasedBlobs() {
361 return DeviceConfigProperties.MAX_LEASED_BLOBS;
362 }
363
364 /**
365 * Returns the maximum number of packages explicitly permitted to access a blob.
366 */
367 public static int getMaxPermittedPackages() {
368 return DeviceConfigProperties.MAX_BLOB_ACCESS_PERMITTED_PACKAGES;
369 }
370
Sudheer Shankaab1d4162020-01-07 10:37:50 -0800371 @Nullable
372 public static File prepareBlobFile(long sessionId) {
373 final File blobsDir = prepareBlobsDir();
374 return blobsDir == null ? null : getBlobFile(blobsDir, sessionId);
375 }
376
377 @NonNull
378 public static File getBlobFile(long sessionId) {
379 return getBlobFile(getBlobsDir(), sessionId);
380 }
381
382 @NonNull
383 private static File getBlobFile(File blobsDir, long sessionId) {
384 return new File(blobsDir, String.valueOf(sessionId));
385 }
386
387 @Nullable
388 public static File prepareBlobsDir() {
389 final File blobsDir = getBlobsDir(prepareBlobStoreRootDir());
390 if (!blobsDir.exists() && !blobsDir.mkdir()) {
391 Slog.e(TAG, "Failed to mkdir(): " + blobsDir);
392 return null;
393 }
394 return blobsDir;
395 }
396
397 @NonNull
398 public static File getBlobsDir() {
399 return getBlobsDir(getBlobStoreRootDir());
400 }
401
402 @NonNull
403 private static File getBlobsDir(File blobsRootDir) {
Sudheer Shanka9f2296a2020-01-25 23:22:34 -0800404 return new File(blobsRootDir, BLOBS_DIR_NAME);
Sudheer Shankaab1d4162020-01-07 10:37:50 -0800405 }
406
407 @Nullable
Sudheer Shankaf6e23b92020-01-15 01:51:15 -0800408 public static File prepareSessionIndexFile() {
409 final File blobStoreRootDir = prepareBlobStoreRootDir();
410 if (blobStoreRootDir == null) {
411 return null;
412 }
Sudheer Shanka9f2296a2020-01-25 23:22:34 -0800413 return new File(blobStoreRootDir, SESSIONS_INDEX_FILE_NAME);
Sudheer Shankaf6e23b92020-01-15 01:51:15 -0800414 }
415
416 @Nullable
417 public static File prepareBlobsIndexFile() {
418 final File blobsStoreRootDir = prepareBlobStoreRootDir();
419 if (blobsStoreRootDir == null) {
420 return null;
421 }
Sudheer Shanka9f2296a2020-01-25 23:22:34 -0800422 return new File(blobsStoreRootDir, BLOBS_INDEX_FILE_NAME);
Sudheer Shankaf6e23b92020-01-15 01:51:15 -0800423 }
424
425 @Nullable
Sudheer Shankaab1d4162020-01-07 10:37:50 -0800426 public static File prepareBlobStoreRootDir() {
427 final File blobStoreRootDir = getBlobStoreRootDir();
428 if (!blobStoreRootDir.exists() && !blobStoreRootDir.mkdir()) {
429 Slog.e(TAG, "Failed to mkdir(): " + blobStoreRootDir);
430 return null;
431 }
432 return blobStoreRootDir;
433 }
434
435 @NonNull
436 public static File getBlobStoreRootDir() {
Sudheer Shanka9f2296a2020-01-25 23:22:34 -0800437 return new File(Environment.getDataSystemDirectory(), ROOT_DIR_NAME);
Sudheer Shankaab1d4162020-01-07 10:37:50 -0800438 }
Sudheer Shanka364364b2020-02-19 17:56:09 -0800439
440 public static void dump(IndentingPrintWriter fout, Context context) {
441 fout.println("XML current version: " + XML_VERSION_CURRENT);
442
443 fout.println("Idle job ID: " + IDLE_JOB_ID);
Sudheer Shanka364364b2020-02-19 17:56:09 -0800444
445 fout.println("Total bytes per app limit: " + formatFileSize(context,
446 getAppDataBytesLimit(), FLAG_IEC_UNITS));
447
448 fout.println("Device config properties:");
449 fout.increaseIndent();
450 DeviceConfigProperties.dump(fout, context);
451 fout.decreaseIndent();
452 }
Sudheer Shankaab1d4162020-01-07 10:37:50 -0800453}