1 /*
2  * Copyright (C) 2010 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.os.storage;
18 
19 import android.os.ParcelFileDescriptor;
20 import android.os.ProxyFileDescriptorCallback;
21 import android.system.ErrnoException;
22 
23 import androidx.test.filters.LargeTest;
24 
25 import com.android.frameworks.coretests.R;
26 
27 import java.io.File;
28 import java.util.concurrent.ThreadFactory;
29 
30 public class StorageManagerIntegrationTest extends StorageManagerBaseTest {
31     private static String LOG_TAG = "StorageManagerIntegrationTest";
32 
33     /**
34      * Tests mounting a single OBB file and verifies its contents.
35      */
36     @LargeTest
testMountSingleObb()37     public void testMountSingleObb() throws Exception {
38         final File file = createObbFile(OBB_FILE_1, R.raw.obb_file1);
39         String filePath = file.getAbsolutePath();
40         mountObb(filePath);
41         verifyObb1Contents(filePath);
42         unmountObb(filePath, DONT_FORCE);
43     }
44 
45     /**
46      * Tests mounting several OBB files and verifies its contents.
47      */
48     @LargeTest
testMountMultipleObb()49     public void testMountMultipleObb() throws Exception {
50         File file1 = null;
51         File file2 = null;
52         File file3 = null;
53         try {
54             file1 = createObbFile(OBB_FILE_1, R.raw.obb_file1);
55             String filePath1 = file1.getAbsolutePath();
56             mountObb(filePath1);
57             verifyObb1Contents(filePath1);
58 
59             file2 = createObbFile(OBB_FILE_2, R.raw.obb_file2);
60             String filePath2 = file2.getAbsolutePath();
61             mountObb(filePath2);
62             verifyObb2Contents(filePath2);
63 
64             file3 = createObbFile(OBB_FILE_3, R.raw.obb_file3);
65             String filePath3 = file3.getAbsolutePath();
66             mountObb(filePath3);
67             verifyObb3Contents(filePath3);
68 
69             unmountObb(filePath1, DONT_FORCE);
70             unmountObb(filePath2, DONT_FORCE);
71             unmountObb(filePath3, DONT_FORCE);
72         } finally {
73             if (file1 != null) {
74                 file1.delete();
75             }
76             if (file2 != null) {
77                 file2.delete();
78             }
79             if (file3 != null) {
80                 file3.delete();
81             }
82         }
83     }
84 
85     /**
86      * Tests mounting a single OBB that isn't signed.
87      */
88     @LargeTest
testMountUnsignedObb()89     public void testMountUnsignedObb() throws Exception {
90         final File file = createObbFile(OBB_FILE_2_UNSIGNED, R.raw.obb_file2_nosign);
91         String filePath = file.getAbsolutePath();
92         try {
93             mountObb(filePath, OnObbStateChangeListener.ERROR_INTERNAL);
94             fail("mountObb should've failed with an exception");
95         } catch (IllegalArgumentException e) {
96             // Expected
97         }
98     }
99 
100     /**
101      * Tests mounting a single OBB that is signed with a different package.
102      */
103     @LargeTest
testMountBadPackageNameObb()104     public void testMountBadPackageNameObb() throws Exception {
105         final File file = createObbFile(OBB_FILE_3_BAD_PACKAGENAME, R.raw.obb_file3_bad_packagename);
106         String filePath = file.getAbsolutePath();
107         mountObb(filePath, OnObbStateChangeListener.ERROR_PERMISSION_DENIED);
108     }
109 
110     /**
111      * Tests remounting a single OBB that has already been mounted.
112      */
113     @LargeTest
testRemountObb()114     public void testRemountObb() throws Exception {
115         final File file = createObbFile(OBB_FILE_1, R.raw.obb_file1);
116         String filePath = file.getAbsolutePath();
117         mountObb(filePath);
118         verifyObb1Contents(filePath);
119         mountObb(filePath, OnObbStateChangeListener.ERROR_ALREADY_MOUNTED);
120         verifyObb1Contents(filePath);
121         unmountObb(filePath, DONT_FORCE);
122     }
123 
124     @LargeTest
testOpenProxyFileDescriptor()125     public void testOpenProxyFileDescriptor() throws Exception {
126         final ProxyFileDescriptorCallback callback = new ProxyFileDescriptorCallback() {
127             @Override
128             public long onGetSize() throws ErrnoException {
129                 return 0;
130             }
131 
132             @Override
133             public void onRelease() {}
134         };
135 
136         final MyThreadFactory factory = new MyThreadFactory();
137         int firstMountId;
138         try (final ParcelFileDescriptor fd = mSm.openProxyFileDescriptor(
139                 ParcelFileDescriptor.MODE_READ_ONLY, callback, null, factory)) {
140             assertNotSame(Thread.State.TERMINATED, factory.thread.getState());
141             firstMountId = mSm.getProxyFileDescriptorMountPointId();
142             assertNotSame(-1, firstMountId);
143         }
144 
145         // After closing descriptor, the loop should terminate.
146         factory.thread.join(3000);
147         assertEquals(Thread.State.TERMINATED, factory.thread.getState());
148 
149         // StorageManager should mount another bridge on the next open request.
150         try (final ParcelFileDescriptor fd = mSm.openProxyFileDescriptor(
151                 ParcelFileDescriptor.MODE_WRITE_ONLY, callback, null, factory)) {
152             assertNotSame(Thread.State.TERMINATED, factory.thread.getState());
153             assertNotSame(firstMountId, mSm.getProxyFileDescriptorMountPointId());
154         }
155     }
156 
157     private static class MyThreadFactory implements ThreadFactory {
158         Thread thread = null;
159 
160         @Override
newThread(Runnable r)161         public Thread newThread(Runnable r) {
162             thread = new Thread(r);
163             return thread;
164         }
165     }
166 }
167