StorageManager.java revision 02c8730c1bf19daf48bec8c6995df676a00a73b1
1/* 2 * Copyright (C) 2008 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 17package android.os.storage; 18 19import android.content.Context; 20import android.os.Binder; 21import android.os.Bundle; 22import android.os.Looper; 23import android.os.Parcelable; 24import android.os.ParcelFileDescriptor; 25import android.os.Process; 26import android.os.RemoteException; 27import android.os.Handler; 28import android.os.Message; 29import android.os.ServiceManager; 30import android.os.storage.IMountService; 31import android.os.storage.IMountServiceListener; 32import android.util.Log; 33import android.util.SparseArray; 34 35import java.io.FileDescriptor; 36import java.io.IOException; 37import java.util.ArrayList; 38import java.util.Collections; 39import java.util.HashMap; 40import java.util.List; 41 42/** 43 * StorageManager is the interface to the systems storage service. 44 * Get an instance of this class by calling 45 * {@link android.content.Context#getSystemService(java.lang.String)} with an argument 46 * of {@link android.content.Context#STORAGE_SERVICE}. 47 */ 48 49public class StorageManager 50{ 51 private static final String TAG = "StorageManager"; 52 53 /* 54 * Our internal MountService binder reference 55 */ 56 private IMountService mMountService; 57 58 /* 59 * The looper target for callbacks 60 */ 61 Looper mTgtLooper; 62 63 /* 64 * Target listener for binder callbacks 65 */ 66 private MountServiceBinderListener mBinderListener; 67 68 /* 69 * List of our listeners 70 */ 71 private ArrayList<ListenerDelegate> mListeners = new ArrayList<ListenerDelegate>(); 72 73 private class MountServiceBinderListener extends IMountServiceListener.Stub { 74 public void onUsbMassStorageConnectionChanged(boolean available) { 75 final int size = mListeners.size(); 76 for (int i = 0; i < size; i++) { 77 mListeners.get(i).sendShareAvailabilityChanged(available); 78 } 79 } 80 81 public void onStorageStateChanged(String path, String oldState, String newState) { 82 final int size = mListeners.size(); 83 for (int i = 0; i < size; i++) { 84 mListeners.get(i).sendStorageStateChanged(path, oldState, newState); 85 } 86 } 87 } 88 89 /** 90 * Private base class for messages sent between the callback thread 91 * and the target looper handler. 92 */ 93 private class StorageEvent { 94 public static final int EVENT_UMS_CONNECTION_CHANGED = 1; 95 public static final int EVENT_STORAGE_STATE_CHANGED = 2; 96 97 private Message mMessage; 98 99 public StorageEvent(int what) { 100 mMessage = Message.obtain(); 101 mMessage.what = what; 102 mMessage.obj = this; 103 } 104 105 public Message getMessage() { 106 return mMessage; 107 } 108 } 109 110 /** 111 * Message sent on a USB mass storage connection change. 112 */ 113 private class UmsConnectionChangedStorageEvent extends StorageEvent { 114 public boolean available; 115 116 public UmsConnectionChangedStorageEvent(boolean a) { 117 super(EVENT_UMS_CONNECTION_CHANGED); 118 available = a; 119 } 120 } 121 122 /** 123 * Message sent on volume state change. 124 */ 125 private class StorageStateChangedStorageEvent extends StorageEvent { 126 public String path; 127 public String oldState; 128 public String newState; 129 130 public StorageStateChangedStorageEvent(String p, String oldS, String newS) { 131 super(EVENT_STORAGE_STATE_CHANGED); 132 path = p; 133 oldState = oldS; 134 newState = newS; 135 } 136 } 137 138 /** 139 * Private class containing sender and receiver code for StorageEvents. 140 */ 141 private class ListenerDelegate { 142 final StorageEventListener mStorageEventListener; 143 private final Handler mHandler; 144 145 ListenerDelegate(StorageEventListener listener) { 146 mStorageEventListener = listener; 147 mHandler = new Handler(mTgtLooper) { 148 @Override 149 public void handleMessage(Message msg) { 150 StorageEvent e = (StorageEvent) msg.obj; 151 152 if (msg.what == StorageEvent.EVENT_UMS_CONNECTION_CHANGED) { 153 UmsConnectionChangedStorageEvent ev = (UmsConnectionChangedStorageEvent) e; 154 mStorageEventListener.onUsbMassStorageConnectionChanged(ev.available); 155 } else if (msg.what == StorageEvent.EVENT_STORAGE_STATE_CHANGED) { 156 StorageStateChangedStorageEvent ev = (StorageStateChangedStorageEvent) e; 157 mStorageEventListener.onStorageStateChanged(ev.path, ev.oldState, ev.newState); 158 } else { 159 Log.e(TAG, "Unsupported event " + msg.what); 160 } 161 } 162 }; 163 } 164 165 StorageEventListener getListener() { 166 return mStorageEventListener; 167 } 168 169 void sendShareAvailabilityChanged(boolean available) { 170 UmsConnectionChangedStorageEvent e = new UmsConnectionChangedStorageEvent(available); 171 mHandler.sendMessage(e.getMessage()); 172 } 173 174 void sendStorageStateChanged(String path, String oldState, String newState) { 175 StorageStateChangedStorageEvent e = new StorageStateChangedStorageEvent(path, oldState, newState); 176 mHandler.sendMessage(e.getMessage()); 177 } 178 } 179 180 /** 181 * Constructs a StorageManager object through which an application can 182 * can communicate with the systems mount service. 183 * 184 * @param tgtLooper The {@android.os.Looper} which events will be received on. 185 * 186 * <p>Applications can get instance of this class by calling 187 * {@link android.content.Context#getSystemService(java.lang.String)} with an argument 188 * of {@link android.content.Context#STORAGE_SERVICE}. 189 * 190 * @hide 191 */ 192 public StorageManager(Looper tgtLooper) throws RemoteException { 193 mMountService = IMountService.Stub.asInterface(ServiceManager.getService("mount")); 194 if (mMountService == null) { 195 Log.e(TAG, "Unable to connect to mount service! - is it running yet?"); 196 return; 197 } 198 mTgtLooper = tgtLooper; 199 mBinderListener = new MountServiceBinderListener(); 200 mMountService.registerListener(mBinderListener); 201 } 202 203 204 /** 205 * Registers a {@link android.os.storage.StorageEventListener StorageEventListener}. 206 * 207 * @param listener A {@link android.os.storage.StorageEventListener StorageEventListener} object. 208 * 209 * @hide 210 */ 211 public void registerListener(StorageEventListener listener) { 212 if (listener == null) { 213 return; 214 } 215 216 synchronized (mListeners) { 217 mListeners.add(new ListenerDelegate(listener)); 218 } 219 } 220 221 /** 222 * Unregisters a {@link android.os.storage.StorageEventListener StorageEventListener}. 223 * 224 * @param listener A {@link android.os.storage.StorageEventListener StorageEventListener} object. 225 * 226 * @hide 227 */ 228 public void unregisterListener(StorageEventListener listener) { 229 if (listener == null) { 230 return; 231 } 232 233 synchronized (mListeners) { 234 final int size = mListeners.size(); 235 for (int i=0 ; i<size ; i++) { 236 ListenerDelegate l = mListeners.get(i); 237 if (l.getListener() == listener) { 238 mListeners.remove(i); 239 break; 240 } 241 } 242 } 243 } 244 245 /** 246 * Enables USB Mass Storage (UMS) on the device. 247 * 248 * @hide 249 */ 250 public void enableUsbMassStorage() { 251 try { 252 mMountService.setUsbMassStorageEnabled(true); 253 } catch (Exception ex) { 254 Log.e(TAG, "Failed to enable UMS", ex); 255 } 256 } 257 258 /** 259 * Disables USB Mass Storage (UMS) on the device. 260 * 261 * @hide 262 */ 263 public void disableUsbMassStorage() { 264 try { 265 mMountService.setUsbMassStorageEnabled(false); 266 } catch (Exception ex) { 267 Log.e(TAG, "Failed to disable UMS", ex); 268 } 269 } 270 271 /** 272 * Query if a USB Mass Storage (UMS) host is connected. 273 * @return true if UMS host is connected. 274 * 275 * @hide 276 */ 277 public boolean isUsbMassStorageConnected() { 278 try { 279 return mMountService.isUsbMassStorageConnected(); 280 } catch (Exception ex) { 281 Log.e(TAG, "Failed to get UMS connection state", ex); 282 } 283 return false; 284 } 285 286 /** 287 * Query if a USB Mass Storage (UMS) is enabled on the device. 288 * @return true if UMS host is enabled. 289 * 290 * @hide 291 */ 292 public boolean isUsbMassStorageEnabled() { 293 try { 294 return mMountService.isUsbMassStorageEnabled(); 295 } catch (RemoteException rex) { 296 Log.e(TAG, "Failed to get UMS enable state", rex); 297 } 298 return false; 299 } 300 301 /** 302 * Mount an OBB file. 303 */ 304 public boolean mountObb(String filename, String key) { 305 try { 306 return mMountService.mountObb(filename, key) 307 == StorageResultCode.OperationSucceeded; 308 } catch (RemoteException e) { 309 Log.e(TAG, "Failed to mount OBB", e); 310 } 311 312 return false; 313 } 314 315 /** 316 * Mount an OBB file. 317 */ 318 public boolean unmountObb(String filename, boolean force) { 319 try { 320 return mMountService.unmountObb(filename, force) 321 == StorageResultCode.OperationSucceeded; 322 } catch (RemoteException e) { 323 Log.e(TAG, "Failed to mount OBB", e); 324 } 325 326 return false; 327 } 328 329 public boolean isObbMounted(String filename) { 330 try { 331 return mMountService.isObbMounted(filename); 332 } catch (RemoteException e) { 333 Log.e(TAG, "Failed to check if OBB is mounted", e); 334 } 335 336 return false; 337 } 338 339 /** 340 * Check the mounted path of an OBB file. 341 */ 342 public String getMountedObbPath(String filename) { 343 try { 344 return mMountService.getMountedObbPath(filename); 345 } catch (RemoteException e) { 346 Log.e(TAG, "Failed to find mounted path for OBB", e); 347 } 348 349 return null; 350 } 351} 352