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