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