1 /*
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  */
16 package com.android.cts.blob.helper;
17 
18 import static android.os.storage.StorageManager.UUID_DEFAULT;
19 
20 import static com.android.utils.blob.Utils.TAG;
21 import static com.android.utils.blob.Utils.writeToSession;
22 
23 import static com.google.common.truth.Truth.assertThat;
24 
25 import android.app.Service;
26 import android.app.blob.BlobHandle;
27 import android.app.blob.BlobStoreManager;
28 import android.app.usage.StorageStats;
29 import android.app.usage.StorageStatsManager;
30 import android.content.Intent;
31 import android.content.pm.PackageManager.NameNotFoundException;
32 import android.os.IBinder;
33 import android.os.LimitExceededException;
34 import android.os.Parcel;
35 import android.os.ParcelFileDescriptor;
36 import android.os.Process;
37 import android.os.RemoteException;
38 import android.util.Log;
39 
40 import com.android.cts.blob.ICommandReceiver;
41 import com.android.utils.blob.Utils;
42 
43 import java.io.IOException;
44 import java.util.concurrent.CompletableFuture;
45 import java.util.concurrent.ExecutionException;
46 import java.util.concurrent.TimeUnit;
47 import java.util.concurrent.TimeoutException;
48 
49 public class BlobStoreTestService extends Service {
50     @Override
onBind(Intent intent)51     public IBinder onBind(Intent intent) {
52         return new CommandReceiver();
53     }
54 
55     private class CommandReceiver extends ICommandReceiver.Stub {
56         @Override
commit(BlobHandle blobHandle, ParcelFileDescriptor input, int accessTypeFlags, long timeoutSec, long size)57         public int commit(BlobHandle blobHandle, ParcelFileDescriptor input, int accessTypeFlags,
58                 long timeoutSec, long size) {
59             final BlobStoreManager blobStoreManager = getSystemService(
60                     BlobStoreManager.class);
61             try {
62                 final long sessionId = blobStoreManager.createSession(blobHandle);
63                 try (BlobStoreManager.Session session = blobStoreManager.openSession(sessionId)) {
64                     writeToSession(session, input, size);
65                     if ((accessTypeFlags & ICommandReceiver.FLAG_ACCESS_TYPE_PUBLIC) != 0) {
66                         session.allowPublicAccess();
67                     }
68 
69                     Log.d(TAG, "Committing session: " + sessionId + "; blob: " + blobHandle);
70                     final CompletableFuture<Integer> callback = new CompletableFuture<>();
71                     session.commit(getMainExecutor(), callback::complete);
72                     return callback.get(timeoutSec, TimeUnit.SECONDS);
73                 }
74             } catch (IOException | InterruptedException | TimeoutException | ExecutionException e) {
75                 throw new IllegalStateException(e);
76             }
77         }
78 
79         @Override
openBlob(BlobHandle blobHandle)80         public ParcelFileDescriptor openBlob(BlobHandle blobHandle) {
81             final BlobStoreManager blobStoreManager = getSystemService(
82                     BlobStoreManager.class);
83             try {
84                 return blobStoreManager.openBlob(blobHandle);
85             } catch (IOException e) {
86                 throw new IllegalStateException(e);
87             }
88         }
89 
90         @Override
openSession(long sessionId)91         public void openSession(long sessionId) {
92             final BlobStoreManager blobStoreManager = getSystemService(
93                     BlobStoreManager.class);
94             try {
95                 try (BlobStoreManager.Session session = blobStoreManager.openSession(sessionId)) {
96                     assertThat(session).isNotNull();
97                 }
98             } catch (IOException e) {
99                 throw new IllegalStateException(e);
100             }
101         }
102 
103         @Override
acquireLease(BlobHandle blobHandle)104         public void acquireLease(BlobHandle blobHandle) {
105             final BlobStoreManager blobStoreManager = getSystemService(
106                     BlobStoreManager.class);
107             try {
108                 Utils.acquireLease(BlobStoreTestService.this, blobHandle, "Test description");
109                 assertThat(blobStoreManager.getLeasedBlobs()).contains(blobHandle);
110             } catch (IOException | LimitExceededException e) {
111                 throw new IllegalStateException(e);
112             }
113         }
114 
115         @Override
releaseLease(BlobHandle blobHandle)116         public void releaseLease(BlobHandle blobHandle) {
117             final BlobStoreManager blobStoreManager = getSystemService(
118                     BlobStoreManager.class);
119             try {
120                 Utils.releaseLease(BlobStoreTestService.this, blobHandle);
121                 assertThat(blobStoreManager.getLeasedBlobs()).doesNotContain(blobHandle);
122             } catch (IOException e) {
123                 throw new IllegalStateException(e);
124             }
125         }
126 
127         @Override
queryStatsForPackage()128         public StorageStats queryStatsForPackage() {
129             final StorageStatsManager storageStatsManager = getSystemService(
130                     StorageStatsManager.class);
131             try {
132                 return storageStatsManager
133                         .queryStatsForPackage(UUID_DEFAULT, getPackageName(), getUser());
134             } catch (IOException | NameNotFoundException e) {
135                 throw new IllegalStateException(e);
136             }
137         }
138 
139         @Override
queryStatsForUid()140         public StorageStats queryStatsForUid() {
141             final StorageStatsManager storageStatsManager = getSystemService(
142                     StorageStatsManager.class);
143             try {
144                 return storageStatsManager
145                         .queryStatsForUid(UUID_DEFAULT, Process.myUid());
146             } catch (IOException e) {
147                 throw new IllegalStateException(e);
148             }
149         }
150 
151         @Override
onTransact(int code, Parcel data, Parcel reply, int flags)152         public boolean onTransact(int code, Parcel data, Parcel reply, int flags)
153                 throws RemoteException {
154             try {
155                 return super.onTransact(code, data, reply, flags);
156             } catch (AssertionError e) {
157                 throw new IllegalStateException(e);
158             }
159         }
160     }
161 }
162