1 /*
2  * Copyright (C) 2015 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 com.android.commands.sm;
18 
19 import android.os.IVoldTaskListener;
20 import android.os.PersistableBundle;
21 import android.os.RemoteException;
22 import android.os.ServiceManager;
23 import android.os.storage.DiskInfo;
24 import android.os.storage.IStorageManager;
25 import android.os.storage.StorageManager;
26 import android.os.storage.VolumeInfo;
27 import android.util.Log;
28 
29 import java.util.concurrent.CompletableFuture;
30 
31 public final class Sm {
32     private static final String TAG = "Sm";
33 
34     IStorageManager mSm;
35 
36     private String[] mArgs;
37     private int mNextArg;
38     private String mCurArgData;
39 
main(String[] args)40     public static void main(String[] args) {
41         boolean success = false;
42         try {
43             new Sm().run(args);
44             success = true;
45         } catch (Exception e) {
46             if (e instanceof IllegalArgumentException) {
47                 showUsage();
48                 System.exit(1);
49             }
50             Log.e(TAG, "Error", e);
51             System.err.println("Error: " + e);
52         }
53         System.exit(success ? 0 : 1);
54     }
55 
run(String[] args)56     public void run(String[] args) throws Exception {
57         if (args.length < 1) {
58             throw new IllegalArgumentException();
59         }
60 
61         mSm = IStorageManager.Stub.asInterface(ServiceManager.getService("mount"));
62         if (mSm == null) {
63             throw new RemoteException("Failed to find running mount service");
64         }
65 
66         mArgs = args;
67         String op = args[0];
68         mNextArg = 1;
69 
70         if ("list-disks".equals(op)) {
71             runListDisks();
72         } else if ("list-volumes".equals(op)) {
73             runListVolumes();
74         } else if ("has-adoptable".equals(op)) {
75             runHasAdoptable();
76         } else if ("get-primary-storage-uuid".equals(op)) {
77             runGetPrimaryStorageUuid();
78         } else if ("set-force-adoptable".equals(op)) {
79             runSetForceAdoptable();
80         } else if ("set-sdcardfs".equals(op)) {
81             runSetSdcardfs();
82         } else if ("partition".equals(op)) {
83             runPartition();
84         } else if ("mount".equals(op)) {
85             runMount();
86         } else if ("unmount".equals(op)) {
87             runUnmount();
88         } else if ("format".equals(op)) {
89             runFormat();
90         } else if ("benchmark".equals(op)) {
91             runBenchmark();
92         } else if ("forget".equals(op)) {
93             runForget();
94         } else if ("set-emulate-fbe".equals(op)) {
95             runSetEmulateFbe();
96         } else if ("get-fbe-mode".equals(op)) {
97             runGetFbeMode();
98         } else if ("idle-maint".equals(op)) {
99             runIdleMaint();
100         } else if ("fstrim".equals(op)) {
101             runFstrim();
102         } else if ("set-virtual-disk".equals(op)) {
103             runSetVirtualDisk();
104         } else if ("set-isolated-storage".equals(op)) {
105             runIsolatedStorage();
106         } else {
107             throw new IllegalArgumentException();
108         }
109     }
110 
runListDisks()111     public void runListDisks() throws RemoteException {
112         final boolean onlyAdoptable = "adoptable".equals(nextArg());
113         final DiskInfo[] disks = mSm.getDisks();
114         for (DiskInfo disk : disks) {
115             if (!onlyAdoptable || disk.isAdoptable()) {
116                 System.out.println(disk.getId());
117             }
118         }
119     }
120 
runListVolumes()121     public void runListVolumes() throws RemoteException {
122         final String filter = nextArg();
123         final int filterType;
124         if ("public".equals(filter)) {
125             filterType = VolumeInfo.TYPE_PUBLIC;
126         } else if ("private".equals(filter)) {
127             filterType = VolumeInfo.TYPE_PRIVATE;
128         } else if ("emulated".equals(filter)) {
129             filterType = VolumeInfo.TYPE_EMULATED;
130         } else if ("stub".equals(filter)) {
131             filterType = VolumeInfo.TYPE_STUB;
132         } else {
133             filterType = -1;
134         }
135 
136         final VolumeInfo[] vols = mSm.getVolumes(0);
137         for (VolumeInfo vol : vols) {
138             if (filterType == -1 || filterType == vol.getType()) {
139                 final String envState = VolumeInfo.getEnvironmentForState(vol.getState());
140                 System.out.println(vol.getId() + " " + envState + " " + vol.getFsUuid());
141             }
142         }
143     }
144 
runHasAdoptable()145     public void runHasAdoptable() {
146         System.out.println(StorageManager.hasAdoptable());
147     }
148 
runGetPrimaryStorageUuid()149     public void runGetPrimaryStorageUuid() throws RemoteException {
150         System.out.println(mSm.getPrimaryStorageUuid());
151     }
152 
runSetForceAdoptable()153     public void runSetForceAdoptable() throws RemoteException {
154         final int mask = StorageManager.DEBUG_ADOPTABLE_FORCE_ON
155                 | StorageManager.DEBUG_ADOPTABLE_FORCE_OFF;
156         switch (nextArg()) {
157             case "on":
158             case "true":
159                 mSm.setDebugFlags(StorageManager.DEBUG_ADOPTABLE_FORCE_ON, mask);
160                 break;
161             case "off":
162                 mSm.setDebugFlags(StorageManager.DEBUG_ADOPTABLE_FORCE_OFF, mask);
163                 break;
164             case "default":
165             case "false":
166                 mSm.setDebugFlags(0, mask);
167                 break;
168         }
169     }
170 
runSetSdcardfs()171     public void runSetSdcardfs() throws RemoteException {
172         final int mask = StorageManager.DEBUG_SDCARDFS_FORCE_ON
173                 | StorageManager.DEBUG_SDCARDFS_FORCE_OFF;
174         switch (nextArg()) {
175             case "on":
176                 mSm.setDebugFlags(StorageManager.DEBUG_SDCARDFS_FORCE_ON, mask);
177                 break;
178             case "off":
179                 mSm.setDebugFlags(StorageManager.DEBUG_SDCARDFS_FORCE_OFF, mask);
180                 break;
181             case "default":
182                 mSm.setDebugFlags(0, mask);
183                 break;
184         }
185     }
186 
runSetEmulateFbe()187     public void runSetEmulateFbe() throws RemoteException {
188         final boolean emulateFbe = Boolean.parseBoolean(nextArg());
189         mSm.setDebugFlags(emulateFbe ? StorageManager.DEBUG_EMULATE_FBE : 0,
190                 StorageManager.DEBUG_EMULATE_FBE);
191     }
192 
runGetFbeMode()193     public void runGetFbeMode() {
194         if (StorageManager.isFileEncryptedNativeOnly()) {
195             System.out.println("native");
196         } else if (StorageManager.isFileEncryptedEmulatedOnly()) {
197             System.out.println("emulated");
198         } else {
199             System.out.println("none");
200         }
201     }
202 
runPartition()203     public void runPartition() throws RemoteException {
204         final String diskId = nextArg();
205         final String type = nextArg();
206         if ("public".equals(type)) {
207             mSm.partitionPublic(diskId);
208         } else if ("private".equals(type)) {
209             mSm.partitionPrivate(diskId);
210         } else if ("mixed".equals(type)) {
211             final int ratio = Integer.parseInt(nextArg());
212             mSm.partitionMixed(diskId, ratio);
213         } else {
214             throw new IllegalArgumentException("Unsupported partition type " + type);
215         }
216     }
217 
runMount()218     public void runMount() throws RemoteException {
219         final String volId = nextArg();
220         mSm.mount(volId);
221     }
222 
runUnmount()223     public void runUnmount() throws RemoteException {
224         final String volId = nextArg();
225         mSm.unmount(volId);
226     }
227 
runFormat()228     public void runFormat() throws RemoteException {
229         final String volId = nextArg();
230         mSm.format(volId);
231     }
232 
runBenchmark()233     public void runBenchmark() throws Exception {
234         final String volId = nextArg();
235         final CompletableFuture<PersistableBundle> result = new CompletableFuture<>();
236         mSm.benchmark(volId, new IVoldTaskListener.Stub() {
237             @Override
238             public void onStatus(int status, PersistableBundle extras) {
239                 // Ignored
240             }
241 
242             @Override
243             public void onFinished(int status, PersistableBundle extras) {
244                 // Touch to unparcel
245                 extras.size();
246                 result.complete(extras);
247             }
248         });
249         System.out.println(result.get());
250     }
251 
runForget()252     public void runForget() throws RemoteException {
253         final String fsUuid = nextArg();
254         if ("all".equals(fsUuid)) {
255             mSm.forgetAllVolumes();
256         } else {
257             mSm.forgetVolume(fsUuid);
258         }
259     }
260 
runFstrim()261     public void runFstrim() throws Exception {
262         final CompletableFuture<PersistableBundle> result = new CompletableFuture<>();
263         mSm.fstrim(0, new IVoldTaskListener.Stub() {
264             @Override
265             public void onStatus(int status, PersistableBundle extras) {
266                 // Ignored
267             }
268 
269             @Override
270             public void onFinished(int status, PersistableBundle extras) {
271                 // Touch to unparcel
272                 extras.size();
273                 result.complete(extras);
274             }
275         });
276         System.out.println(result.get());
277     }
278 
runSetVirtualDisk()279     public void runSetVirtualDisk() throws RemoteException {
280         final boolean virtualDisk = Boolean.parseBoolean(nextArg());
281         mSm.setDebugFlags(virtualDisk ? StorageManager.DEBUG_VIRTUAL_DISK : 0,
282                 StorageManager.DEBUG_VIRTUAL_DISK);
283     }
284 
runIsolatedStorage()285     public void runIsolatedStorage() throws RemoteException {
286         final int value;
287         final int mask = StorageManager.DEBUG_ISOLATED_STORAGE_FORCE_ON
288                 | StorageManager.DEBUG_ISOLATED_STORAGE_FORCE_OFF;
289         switch (nextArg()) {
290             case "on":
291             case "true":
292                 value = StorageManager.DEBUG_ISOLATED_STORAGE_FORCE_ON;
293                 break;
294             case "off":
295                 value = StorageManager.DEBUG_ISOLATED_STORAGE_FORCE_OFF;
296                 break;
297             case "default":
298             case "false":
299                 value = 0;
300                 break;
301             default:
302                 return;
303         }
304         mSm.setDebugFlags(value, mask);
305     }
306 
runIdleMaint()307     public void runIdleMaint() throws RemoteException {
308         final boolean im_run = "run".equals(nextArg());
309         if (im_run) {
310             mSm.runIdleMaintenance();
311         } else {
312             mSm.abortIdleMaintenance();
313         }
314     }
315 
nextArg()316     private String nextArg() {
317         if (mNextArg >= mArgs.length) {
318             return null;
319         }
320         String arg = mArgs[mNextArg];
321         mNextArg++;
322         return arg;
323     }
324 
showUsage()325     private static int showUsage() {
326         System.err.println("usage: sm list-disks [adoptable]");
327         System.err.println("       sm list-volumes [public|private|emulated|stub|all]");
328         System.err.println("       sm has-adoptable");
329         System.err.println("       sm get-primary-storage-uuid");
330         System.err.println("       sm set-force-adoptable [on|off|default]");
331         System.err.println("       sm set-virtual-disk [true|false]");
332         System.err.println("");
333         System.err.println("       sm partition DISK [public|private|mixed] [ratio]");
334         System.err.println("       sm mount VOLUME");
335         System.err.println("       sm unmount VOLUME");
336         System.err.println("       sm format VOLUME");
337         System.err.println("       sm benchmark VOLUME");
338         System.err.println("       sm idle-maint [run|abort]");
339         System.err.println("       sm fstrim");
340         System.err.println("");
341         System.err.println("       sm forget [UUID|all]");
342         System.err.println("");
343         System.err.println("       sm set-emulate-fbe [true|false]");
344         System.err.println("");
345         System.err.println("       sm set-isolated-storage [on|off|default]");
346         System.err.println("");
347         return 1;
348     }
349 }
350