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 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 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 { 105 throw new IllegalArgumentException(); 106 } 107 } 108 109 public void runListDisks() throws RemoteException { 110 final boolean onlyAdoptable = "adoptable".equals(nextArg()); 111 final DiskInfo[] disks = mSm.getDisks(); 112 for (DiskInfo disk : disks) { 113 if (!onlyAdoptable || disk.isAdoptable()) { 114 System.out.println(disk.getId()); 115 } 116 } 117 } 118 119 public void runListVolumes() throws RemoteException { 120 final String filter = nextArg(); 121 final int filterType; 122 if ("public".equals(filter)) { 123 filterType = VolumeInfo.TYPE_PUBLIC; 124 } else if ("private".equals(filter)) { 125 filterType = VolumeInfo.TYPE_PRIVATE; 126 } else if ("emulated".equals(filter)) { 127 filterType = VolumeInfo.TYPE_EMULATED; 128 } else { 129 filterType = -1; 130 } 131 132 final VolumeInfo[] vols = mSm.getVolumes(0); 133 for (VolumeInfo vol : vols) { 134 if (filterType == -1 || filterType == vol.getType()) { 135 final String envState = VolumeInfo.getEnvironmentForState(vol.getState()); 136 System.out.println(vol.getId() + " " + envState + " " + vol.getFsUuid()); 137 } 138 } 139 } 140 141 public void runHasAdoptable() { 142 System.out.println(StorageManager.hasAdoptable()); 143 } 144 145 public void runGetPrimaryStorageUuid() throws RemoteException { 146 System.out.println(mSm.getPrimaryStorageUuid()); 147 } 148 149 public void runSetForceAdoptable() throws RemoteException { 150 final int mask = StorageManager.DEBUG_ADOPTABLE_FORCE_ON 151 | StorageManager.DEBUG_ADOPTABLE_FORCE_OFF; 152 switch (nextArg()) { 153 case "on": 154 case "true": 155 mSm.setDebugFlags(StorageManager.DEBUG_ADOPTABLE_FORCE_ON, mask); 156 break; 157 case "off": 158 mSm.setDebugFlags(StorageManager.DEBUG_ADOPTABLE_FORCE_OFF, mask); 159 break; 160 case "default": 161 case "false": 162 mSm.setDebugFlags(0, mask); 163 break; 164 } 165 } 166 167 public void runSetSdcardfs() throws RemoteException { 168 final int mask = StorageManager.DEBUG_SDCARDFS_FORCE_ON 169 | StorageManager.DEBUG_SDCARDFS_FORCE_OFF; 170 switch (nextArg()) { 171 case "on": 172 mSm.setDebugFlags(StorageManager.DEBUG_SDCARDFS_FORCE_ON, mask); 173 break; 174 case "off": 175 mSm.setDebugFlags(StorageManager.DEBUG_SDCARDFS_FORCE_OFF, mask); 176 break; 177 case "default": 178 mSm.setDebugFlags(0, mask); 179 break; 180 } 181 } 182 183 public void runSetEmulateFbe() throws RemoteException { 184 final boolean emulateFbe = Boolean.parseBoolean(nextArg()); 185 mSm.setDebugFlags(emulateFbe ? StorageManager.DEBUG_EMULATE_FBE : 0, 186 StorageManager.DEBUG_EMULATE_FBE); 187 } 188 189 public void runGetFbeMode() { 190 if (StorageManager.isFileEncryptedNativeOnly()) { 191 System.out.println("native"); 192 } else if (StorageManager.isFileEncryptedEmulatedOnly()) { 193 System.out.println("emulated"); 194 } else { 195 System.out.println("none"); 196 } 197 } 198 199 public void runPartition() throws RemoteException { 200 final String diskId = nextArg(); 201 final String type = nextArg(); 202 if ("public".equals(type)) { 203 mSm.partitionPublic(diskId); 204 } else if ("private".equals(type)) { 205 mSm.partitionPrivate(diskId); 206 } else if ("mixed".equals(type)) { 207 final int ratio = Integer.parseInt(nextArg()); 208 mSm.partitionMixed(diskId, ratio); 209 } else { 210 throw new IllegalArgumentException("Unsupported partition type " + type); 211 } 212 } 213 214 public void runMount() throws RemoteException { 215 final String volId = nextArg(); 216 mSm.mount(volId); 217 } 218 219 public void runUnmount() throws RemoteException { 220 final String volId = nextArg(); 221 mSm.unmount(volId); 222 } 223 224 public void runFormat() throws RemoteException { 225 final String volId = nextArg(); 226 mSm.format(volId); 227 } 228 229 public void runBenchmark() throws Exception { 230 final String volId = nextArg(); 231 final CompletableFuture<PersistableBundle> result = new CompletableFuture<>(); 232 mSm.benchmark(volId, new IVoldTaskListener.Stub() { 233 @Override 234 public void onStatus(int status, PersistableBundle extras) { 235 // Ignored 236 } 237 238 @Override 239 public void onFinished(int status, PersistableBundle extras) { 240 // Touch to unparcel 241 extras.size(); 242 result.complete(extras); 243 } 244 }); 245 System.out.println(result.get()); 246 } 247 248 public void runForget() throws RemoteException { 249 final String fsUuid = nextArg(); 250 if ("all".equals(fsUuid)) { 251 mSm.forgetAllVolumes(); 252 } else { 253 mSm.forgetVolume(fsUuid); 254 } 255 } 256 257 public void runFstrim() throws Exception { 258 final CompletableFuture<PersistableBundle> result = new CompletableFuture<>(); 259 mSm.fstrim(0, new IVoldTaskListener.Stub() { 260 @Override 261 public void onStatus(int status, PersistableBundle extras) { 262 // Ignored 263 } 264 265 @Override 266 public void onFinished(int status, PersistableBundle extras) { 267 // Touch to unparcel 268 extras.size(); 269 result.complete(extras); 270 } 271 }); 272 System.out.println(result.get()); 273 } 274 275 public void runSetVirtualDisk() throws RemoteException { 276 final boolean virtualDisk = Boolean.parseBoolean(nextArg()); 277 mSm.setDebugFlags(virtualDisk ? StorageManager.DEBUG_VIRTUAL_DISK : 0, 278 StorageManager.DEBUG_VIRTUAL_DISK); 279 } 280 281 public void runIdleMaint() throws RemoteException { 282 final boolean im_run = "run".equals(nextArg()); 283 if (im_run) { 284 mSm.runIdleMaintenance(); 285 } else { 286 mSm.abortIdleMaintenance(); 287 } 288 } 289 290 private String nextArg() { 291 if (mNextArg >= mArgs.length) { 292 return null; 293 } 294 String arg = mArgs[mNextArg]; 295 mNextArg++; 296 return arg; 297 } 298 299 private static int showUsage() { 300 System.err.println("usage: sm list-disks [adoptable]"); 301 System.err.println(" sm list-volumes [public|private|emulated|all]"); 302 System.err.println(" sm has-adoptable"); 303 System.err.println(" sm get-primary-storage-uuid"); 304 System.err.println(" sm set-force-adoptable [on|off|default]"); 305 System.err.println(" sm set-virtual-disk [true|false]"); 306 System.err.println(""); 307 System.err.println(" sm partition DISK [public|private|mixed] [ratio]"); 308 System.err.println(" sm mount VOLUME"); 309 System.err.println(" sm unmount VOLUME"); 310 System.err.println(" sm format VOLUME"); 311 System.err.println(" sm benchmark VOLUME"); 312 System.err.println(" sm idle-maint [run|abort]"); 313 System.err.println(" sm fstrim"); 314 System.err.println(""); 315 System.err.println(" sm forget [UUID|all]"); 316 System.err.println(""); 317 System.err.println(" sm set-emulate-fbe [true|false]"); 318 System.err.println(""); 319 return 1; 320 } 321 } 322