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 import android.test.suitebuilder.annotation.LargeTest; 23 import android.util.Log; 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 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 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 encrypted OBB file and verifies its contents. 87 */ 88 @LargeTest 89 public void testMountSingleEncryptedObb() throws Exception { 90 final File file = createObbFile(OBB_FILE_3_ENCRYPTED, R.raw.obb_enc_file100_orig3); 91 String filePath = file.getAbsolutePath(); 92 mountObb(filePath, OBB_FILE_3_PASSWORD, OnObbStateChangeListener.MOUNTED); 93 verifyObb3Contents(filePath); 94 unmountObb(filePath, DONT_FORCE); 95 } 96 97 /** 98 * Tests mounting a single encrypted OBB file using an invalid password. 99 */ 100 @LargeTest 101 public void testMountSingleEncryptedObbInvalidPassword() throws Exception { 102 final File file = createObbFile("bad password@$%#@^*(!&)", R.raw.obb_enc_file100_orig3); 103 String filePath = file.getAbsolutePath(); 104 mountObb(filePath, OBB_FILE_1_PASSWORD, OnObbStateChangeListener.ERROR_COULD_NOT_MOUNT); 105 } 106 107 /** 108 * Tests simultaneously mounting 2 encrypted OBBs with different keys and verifies contents. 109 */ 110 @LargeTest 111 public void testMountTwoEncryptedObb() throws Exception { 112 File file3 = null; 113 File file1 = null; 114 try { 115 file3 = createObbFile(OBB_FILE_3_ENCRYPTED, R.raw.obb_enc_file100_orig3); 116 String filePath3 = file3.getAbsolutePath(); 117 mountObb(filePath3, OBB_FILE_3_PASSWORD, OnObbStateChangeListener.MOUNTED); 118 verifyObb3Contents(filePath3); 119 120 file1 = createObbFile(OBB_FILE_1_ENCRYPTED, R.raw.obb_enc_file100_orig1); 121 String filePath1 = file1.getAbsolutePath(); 122 mountObb(filePath1, OBB_FILE_1_PASSWORD, OnObbStateChangeListener.MOUNTED); 123 verifyObb1Contents(filePath1); 124 125 unmountObb(filePath3, DONT_FORCE); 126 unmountObb(filePath1, DONT_FORCE); 127 } finally { 128 if (file3 != null) { 129 file3.delete(); 130 } 131 if (file1 != null) { 132 file1.delete(); 133 } 134 } 135 } 136 137 /** 138 * Tests that we can not force unmount when a file is currently open on the OBB. 139 */ 140 @LargeTest 141 public void testUnmount_DontForce() throws Exception { 142 final File file = createObbFile(OBB_FILE_1, R.raw.obb_file1); 143 String obbFilePath = file.getAbsolutePath(); 144 145 MountingObbThread mountingThread = new MountingObbThread(obbFilePath, 146 OBB_FILE_1_CONTENTS_1); 147 148 try { 149 mountingThread.start(); 150 151 long waitTime = 0; 152 while (!mountingThread.isFileOpenOnObb()) { 153 synchronized (mountingThread) { 154 Log.i(LOG_TAG, "Waiting for file to be opened on OBB..."); 155 mountingThread.wait(WAIT_TIME_INCR); 156 waitTime += WAIT_TIME_INCR; 157 if (waitTime > MAX_WAIT_TIME) { 158 fail("Timed out waiting for file file to be opened on OBB!"); 159 } 160 } 161 } 162 163 unmountObb(obbFilePath, DONT_FORCE); 164 165 // verify still mounted 166 assertTrue("mounted path should not be null!", obbFilePath != null); 167 assertTrue("mounted path should still be mounted!", mSm.isObbMounted(obbFilePath)); 168 169 // close the opened file 170 mountingThread.doStop(); 171 172 // try unmounting again (should succeed this time) 173 unmountObb(obbFilePath, DONT_FORCE); 174 assertFalse("mounted path should no longer be mounted!", 175 mSm.isObbMounted(obbFilePath)); 176 } catch (InterruptedException e) { 177 fail("Timed out waiting for file on OBB to be opened..."); 178 } 179 } 180 181 /** 182 * Tests mounting a single OBB that isn't signed. 183 */ 184 @LargeTest 185 public void testMountUnsignedObb() throws Exception { 186 final File file = createObbFile(OBB_FILE_2_UNSIGNED, R.raw.obb_file2_nosign); 187 String filePath = file.getAbsolutePath(); 188 mountObb(filePath, OBB_FILE_2_UNSIGNED, OnObbStateChangeListener.ERROR_INTERNAL); 189 } 190 191 /** 192 * Tests mounting a single OBB that is signed with a different package. 193 */ 194 @LargeTest 195 public void testMountBadPackageNameObb() throws Exception { 196 final File file = createObbFile(OBB_FILE_3_BAD_PACKAGENAME, R.raw.obb_file3_bad_packagename); 197 String filePath = file.getAbsolutePath(); 198 mountObb(filePath, OBB_FILE_3_BAD_PACKAGENAME, 199 OnObbStateChangeListener.ERROR_PERMISSION_DENIED); 200 } 201 202 /** 203 * Tests remounting a single OBB that has already been mounted. 204 */ 205 @LargeTest 206 public void testRemountObb() throws Exception { 207 final File file = createObbFile(OBB_FILE_1, R.raw.obb_file1); 208 String filePath = file.getAbsolutePath(); 209 mountObb(filePath); 210 verifyObb1Contents(filePath); 211 mountObb(filePath, null, OnObbStateChangeListener.ERROR_ALREADY_MOUNTED); 212 verifyObb1Contents(filePath); 213 unmountObb(filePath, DONT_FORCE); 214 } 215 216 @LargeTest 217 public void testOpenProxyFileDescriptor() throws Exception { 218 final ProxyFileDescriptorCallback callback = new ProxyFileDescriptorCallback() { 219 @Override 220 public long onGetSize() throws ErrnoException { 221 return 0; 222 } 223 224 @Override 225 public void onRelease() {} 226 }; 227 228 final MyThreadFactory factory = new MyThreadFactory(); 229 int firstMountId; 230 try (final ParcelFileDescriptor fd = mSm.openProxyFileDescriptor( 231 ParcelFileDescriptor.MODE_READ_ONLY, callback, null, factory)) { 232 assertNotSame(Thread.State.TERMINATED, factory.thread.getState()); 233 firstMountId = mSm.getProxyFileDescriptorMountPointId(); 234 assertNotSame(-1, firstMountId); 235 } 236 237 // After closing descriptor, the loop should terminate. 238 factory.thread.join(3000); 239 assertEquals(Thread.State.TERMINATED, factory.thread.getState()); 240 241 // StorageManager should mount another bridge on the next open request. 242 try (final ParcelFileDescriptor fd = mSm.openProxyFileDescriptor( 243 ParcelFileDescriptor.MODE_WRITE_ONLY, callback, null, factory)) { 244 assertNotSame(Thread.State.TERMINATED, factory.thread.getState()); 245 assertNotSame(firstMountId, mSm.getProxyFileDescriptorMountPointId()); 246 } 247 } 248 249 private static class MyThreadFactory implements ThreadFactory { 250 Thread thread = null; 251 252 @Override 253 public Thread newThread(Runnable r) { 254 thread = new Thread(r); 255 return thread; 256 } 257 } 258 } 259