StorageManager.java revision 6f63dd5dc8ae38f866e297883435dd1fd3a5cdfd
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 * @hide 49 * 50 */ 51 52public class StorageManager 53{ 54 private static final String TAG = "StorageManager"; 55 56 /* 57 * Our internal MountService binder reference 58 */ 59 private IMountService mMountService; 60 61 /* 62 * The looper target for callbacks 63 */ 64 Looper mTgtLooper; 65 66 /* 67 * Target listener for binder callbacks 68 */ 69 private MountServiceBinderListener mBinderListener; 70 71 /* 72 * List of our listeners 73 */ 74 private ArrayList<ListenerDelegate> mListeners = new ArrayList<ListenerDelegate>(); 75 76 private class MountServiceBinderListener extends IMountServiceListener.Stub { 77 public void onUsbMassStorageConnectionChanged(boolean available) { 78 final int size = mListeners.size(); 79 for (int i = 0; i < size; i++) { 80 mListeners.get(i).sendShareAvailabilityChanged(available); 81 } 82 } 83 84 public void onStorageStateChanged(String path, String oldState, String newState) { 85 final int size = mListeners.size(); 86 for (int i = 0; i < size; i++) { 87 mListeners.get(i).sendStorageStateChanged(path, oldState, newState); 88 } 89 } 90 } 91 92 /** 93 * Private base class for messages sent between the callback thread 94 * and the target looper handler. 95 */ 96 private class StorageEvent { 97 public static final int EVENT_UMS_CONNECTION_CHANGED = 1; 98 public static final int EVENT_STORAGE_STATE_CHANGED = 2; 99 100 private Message mMessage; 101 102 public StorageEvent(int what) { 103 mMessage = Message.obtain(); 104 mMessage.what = what; 105 mMessage.obj = this; 106 } 107 108 public Message getMessage() { 109 return mMessage; 110 } 111 } 112 113 /** 114 * Message sent on a USB mass storage connection change. 115 */ 116 private class UmsConnectionChangedStorageEvent extends StorageEvent { 117 public boolean available; 118 119 public UmsConnectionChangedStorageEvent(boolean a) { 120 super(EVENT_UMS_CONNECTION_CHANGED); 121 available = a; 122 } 123 } 124 125 /** 126 * Message sent on volume state change. 127 */ 128 private class StorageStateChangedStorageEvent extends StorageEvent { 129 public String path; 130 public String oldState; 131 public String newState; 132 133 public StorageStateChangedStorageEvent(String p, String oldS, String newS) { 134 super(EVENT_STORAGE_STATE_CHANGED); 135 path = p; 136 oldState = oldS; 137 newState = newS; 138 } 139 } 140 141 /** 142 * Private class containing sender and receiver code for StorageEvents. 143 */ 144 private class ListenerDelegate { 145 final StorageEventListener mStorageEventListener; 146 private final Handler mHandler; 147 148 ListenerDelegate(StorageEventListener listener) { 149 mStorageEventListener = listener; 150 mHandler = new Handler(mTgtLooper) { 151 @Override 152 public void handleMessage(Message msg) { 153 StorageEvent e = (StorageEvent) msg.obj; 154 155 if (msg.what == StorageEvent.EVENT_UMS_CONNECTION_CHANGED) { 156 UmsConnectionChangedStorageEvent ev = (UmsConnectionChangedStorageEvent) e; 157 mStorageEventListener.onUsbMassStorageConnectionChanged(ev.available); 158 } else if (msg.what == StorageEvent.EVENT_STORAGE_STATE_CHANGED) { 159 StorageStateChangedStorageEvent ev = (StorageStateChangedStorageEvent) e; 160 mStorageEventListener.onStorageStateChanged(ev.path, ev.oldState, ev.newState); 161 } else { 162 Log.e(TAG, "Unsupported event " + msg.what); 163 } 164 } 165 }; 166 } 167 168 StorageEventListener getListener() { 169 return mStorageEventListener; 170 } 171 172 void sendShareAvailabilityChanged(boolean available) { 173 UmsConnectionChangedStorageEvent e = new UmsConnectionChangedStorageEvent(available); 174 mHandler.sendMessage(e.getMessage()); 175 } 176 177 void sendStorageStateChanged(String path, String oldState, String newState) { 178 StorageStateChangedStorageEvent e = new StorageStateChangedStorageEvent(path, oldState, newState); 179 mHandler.sendMessage(e.getMessage()); 180 } 181 } 182 183 /** 184 * Constructs a StorageManager object through which an application can 185 * can communicate with the systems mount service. 186 * 187 * @param tgtLooper The {@android.os.Looper} which events will be received on. 188 * 189 * <p>Applications can get instance of this class by calling 190 * {@link android.content.Context#getSystemService(java.lang.String)} with an argument 191 * of {@link android.content.Context#STORAGE_SERVICE}. 192 * 193 * @hide 194 */ 195 public StorageManager(Looper tgtLooper) throws RemoteException { 196 mMountService = IMountService.Stub.asInterface(ServiceManager.getService("mount")); 197 if (mMountService == null) { 198 Log.e(TAG, "Unable to connect to mount service! - is it running yet?"); 199 return; 200 } 201 mTgtLooper = tgtLooper; 202 mBinderListener = new MountServiceBinderListener(); 203 mMountService.registerListener(mBinderListener); 204 } 205 206 207 /** 208 * Registers a {@link android.os.storage.StorageEventListener StorageEventListener}. 209 * 210 * @param listener A {@link android.os.storage.StorageEventListener StorageEventListener} object. 211 * 212 */ 213 public void registerListener(StorageEventListener listener) { 214 if (listener == null) { 215 return; 216 } 217 218 synchronized (mListeners) { 219 mListeners.add(new ListenerDelegate(listener)); 220 } 221 } 222 223 /** 224 * Unregisters a {@link android.os.storage.StorageEventListener StorageEventListener}. 225 * 226 * @param listener A {@link android.os.storage.StorageEventListener StorageEventListener} object. 227 * 228 */ 229 public void unregisterListener(StorageEventListener listener) { 230 if (listener == null) { 231 return; 232 } 233 234 synchronized (mListeners) { 235 final int size = mListeners.size(); 236 for (int i=0 ; i<size ; i++) { 237 ListenerDelegate l = mListeners.get(i); 238 if (l.getListener() == listener) { 239 mListeners.remove(i); 240 break; 241 } 242 } 243 } 244 } 245 246 /** 247 * Enables USB Mass Storage (UMS) on the device. 248 */ 249 public void enableUsbMassStorage() { 250 try { 251 mMountService.setUsbMassStorageEnabled(true); 252 } catch (Exception ex) { 253 Log.e(TAG, "Failed to enable UMS", ex); 254 } 255 } 256 257 /** 258 * Disables USB Mass Storage (UMS) on the device. 259 */ 260 public void disableUsbMassStorage() { 261 try { 262 mMountService.setUsbMassStorageEnabled(false); 263 } catch (Exception ex) { 264 Log.e(TAG, "Failed to disable UMS", ex); 265 } 266 } 267 268 /** 269 * Query if a USB Mass Storage (UMS) host is connected. 270 * @return true if UMS host is connected. 271 */ 272 public boolean isUsbMassStorageConnected() { 273 try { 274 return mMountService.isUsbMassStorageConnected(); 275 } catch (Exception ex) { 276 Log.e(TAG, "Failed to get UMS connection state", ex); 277 } 278 return false; 279 } 280 281 /** 282 * Query if a USB Mass Storage (UMS) is enabled on the device. 283 * @return true if UMS host is enabled. 284 */ 285 public boolean isUsbMassStorageEnabled() { 286 try { 287 return mMountService.isUsbMassStorageEnabled(); 288 } catch (RemoteException rex) { 289 Log.e(TAG, "Failed to get UMS enable state", rex); 290 } 291 return false; 292 } 293} 294