• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2022 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.cts;
18 
19 import android.os.ParcelFileDescriptor;
20 import android.util.Log;
21 
22 import androidx.test.platform.app.InstrumentationRegistry;
23 
24 import com.google.common.collect.Iterables;
25 
26 import java.io.BufferedReader;
27 import java.io.FileInputStream;
28 import java.io.InputStream;
29 import java.io.InputStreamReader;
30 import java.nio.charset.StandardCharsets;
31 import java.util.ArrayList;
32 import java.util.List;
33 import java.util.concurrent.TimeoutException;
34 import java.util.function.Supplier;
35 
36 final class StorageManagerHelper {
37 
38     /**
39      * Creates a virtual disk that simulates SDCard on a device. It is
40      * mounted as a public visible disk.
41      * @return the volume name of the disk just created
42      * @throws Exception, if the volume could not be created
43      */
createSDCardVirtualDisk()44     static String createSDCardVirtualDisk() throws Exception {
45         return createDiskAndGetVolumeName(true);
46     }
47     /**
48      * Creates a virtual disk that simulates USB on a device. It is
49      * mounted as a public invisible disk.
50      * @return the volume name of the disk just created
51      * @throws Exception, if the volume could not be created
52      */
createUSBVirtualDisk()53     static String createUSBVirtualDisk() throws Exception {
54         return createDiskAndGetVolumeName(false);
55     }
56 
57     /**
58      * Removes the simulated disk
59      */
removeVirtualDisk()60     static void removeVirtualDisk() throws Exception {
61         executeShellCommand("sm set-virtual-disk false");
62         //sleep to make sure that it is unmounted
63         Thread.sleep(5000);
64     }
65 
66     /**
67      * Create a public volume for testing and only return the one newly created as the volumeName.
68      */
createDiskAndGetVolumeName(boolean visible)69     public static String createDiskAndGetVolumeName(boolean visible) throws Exception {
70         //remove any existing volume that was mounted before
71         removeVirtualDisk();
72         String existingPublicVolume = getPublicVolumeExcluding(null);
73         executeShellCommand("sm set-force-adoptable " + (visible ? "on" : "off"));
74         executeShellCommand("sm set-virtual-disk true");
75         Thread.sleep(10000);
76         pollForCondition(StorageManagerHelper::partitionDisks,
77                 "Could not create public volume in time");
78         return getPublicVolumeExcluding(existingPublicVolume);
79     }
80 
partitionDisks()81     private static boolean partitionDisks() {
82         try {
83             List<String> diskNames = executeShellCommand("sm list-disks");
84             if (!diskNames.isEmpty()) {
85                 executeShellCommand("sm partition " + Iterables.getLast(diskNames) + " public");
86                 return true;
87             }
88         } catch (Exception ignored) {
89             //ignored
90         }
91         return false;
92     }
93 
pollForCondition(Supplier<Boolean> condition, String errorMessage)94     private static void pollForCondition(Supplier<Boolean> condition, String errorMessage)
95             throws Exception {
96         Thread.sleep(2000);
97         for (int i = 0; i < 20; i++) {
98             if (condition.get()) {
99                 return;
100             }
101             Thread.sleep(100);
102         }
103         throw new TimeoutException(errorMessage);
104     }
105 
getPublicVolumeExcluding(String excludingVolume)106     private static String getPublicVolumeExcluding(String excludingVolume) throws Exception {
107 
108         List<String> volumes = executeShellCommand("sm list-volumes");
109         // list volumes will result in something like
110         // private mounted null
111         // public:7,281 mounted 3080-17E8
112         // emulated;0 mounted null
113         // and we are interested in 3080-17E8
114         for (String volume: volumes) {
115             if (volume.contains("public")
116                     && (excludingVolume == null || !volume.contains(excludingVolume))) {
117                 //public:7,281 mounted 3080-17E8
118                 String[] splits = volume.split(" ");
119                 //Return the last snippet, that is 3080-17E8
120                 return splits[splits.length - 1];
121             }
122         }
123         return null;
124     }
125 
executeShellCommand(String command)126     private static List<String> executeShellCommand(String command) throws Exception {
127         final ParcelFileDescriptor pfd = InstrumentationRegistry.getInstrumentation()
128                 .getUiAutomation().executeShellCommand(command);
129         BufferedReader br = null;
130         try (InputStream in = new FileInputStream(pfd.getFileDescriptor())) {
131             br = new BufferedReader(new InputStreamReader(in, StandardCharsets.UTF_8));
132             String str = null;
133             List<String> output = new ArrayList<>();
134             while ((str = br.readLine()) != null) {
135                 output.add(str);
136             }
137             return output;
138         } finally {
139             if (br != null) {
140                 closeQuietly(br);
141             }
142             closeQuietly(pfd);
143         }
144     }
145 
closeQuietly(AutoCloseable closeable)146     private static void closeQuietly(AutoCloseable closeable) {
147         if (closeable != null) {
148 
149             try {
150                 closeable.close();
151             } catch (RuntimeException rethrown) {
152                 throw rethrown;
153             } catch (Exception ignored) {
154                 Log.w("StorageManagerHelper", ignored.getMessage());
155             }
156         }
157     }
158 }
159