UsbStorageActivity.java revision 77bc30d232633eb36323245bc5d0cbf144a3bd26
1/*
2 * Copyright (C) 2007 Google Inc.
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 com.android.systemui.usb;
18
19import com.android.internal.R;
20import android.app.Activity;
21import android.app.ActivityManager;
22import android.app.AlertDialog;
23import android.app.Dialog;
24import android.content.BroadcastReceiver;
25import android.content.Context;
26import android.content.DialogInterface;
27import android.content.Intent;
28import android.content.IntentFilter;
29import android.content.DialogInterface.OnCancelListener;
30import android.content.pm.ApplicationInfo;
31import android.content.pm.PackageManager;
32import android.content.pm.PackageManager.NameNotFoundException;
33import android.hardware.Usb;
34import android.os.Bundle;
35import android.os.Environment;
36import android.os.Handler;
37import android.os.IBinder;
38import android.os.storage.IMountService;
39import android.os.storage.StorageManager;
40import android.os.storage.StorageEventListener;
41import android.os.RemoteException;
42import android.os.ServiceManager;
43import android.widget.ImageView;
44import android.widget.Button;
45import android.widget.ProgressBar;
46import android.widget.TextView;
47import android.view.View;
48import android.view.Window;
49import android.util.Log;
50
51import java.util.List;
52
53/**
54 * This activity is shown to the user for him/her to enable USB mass storage
55 * on-demand (that is, when the USB cable is connected). It uses the alert
56 * dialog style. It will be launched from a notification.
57 */
58public class UsbStorageActivity extends Activity
59        implements View.OnClickListener, OnCancelListener {
60    private static final String TAG = "UsbStorageActivity";
61
62    private Button mMountButton;
63    private Button mUnmountButton;
64    private ProgressBar mProgressBar;
65    private TextView mBanner;
66    private TextView mMessage;
67    private ImageView mIcon;
68    private StorageManager mStorageManager = null;
69    private static final int DLG_CONFIRM_KILL_STORAGE_USERS = 1;
70    private static final int DLG_ERROR_SHARING = 2;
71    static final boolean localLOGV = false;
72
73    /** Used to detect when the USB cable is unplugged, so we can call finish() */
74    private BroadcastReceiver mUsbStateReceiver = new BroadcastReceiver() {
75        @Override
76        public void onReceive(Context context, Intent intent) {
77            if (intent.getAction().equals(Usb.ACTION_USB_STATE)) {
78                handleUsbStateChanged(intent);
79            }
80        }
81    };
82
83    private StorageEventListener mStorageListener = new StorageEventListener() {
84        @Override
85        public void onStorageStateChanged(String path, String oldState, String newState) {
86            final boolean on = newState.equals(Environment.MEDIA_SHARED);
87            switchDisplay(on);
88        }
89    };
90
91    @Override
92    protected void onCreate(Bundle savedInstanceState) {
93        super.onCreate(savedInstanceState);
94
95        if (mStorageManager == null) {
96            mStorageManager = (StorageManager) getSystemService(Context.STORAGE_SERVICE);
97            if (mStorageManager == null) {
98                Log.w(TAG, "Failed to get StorageManager");
99            }
100        }
101
102        requestWindowFeature(Window.FEATURE_INDETERMINATE_PROGRESS);
103        setProgressBarIndeterminateVisibility(true);
104
105        setTitle(getString(com.android.internal.R.string.usb_storage_activity_title));
106
107        setContentView(com.android.internal.R.layout.usb_storage_activity);
108
109        mIcon = (ImageView) findViewById(com.android.internal.R.id.icon);
110        mBanner = (TextView) findViewById(com.android.internal.R.id.banner);
111        mMessage = (TextView) findViewById(com.android.internal.R.id.message);
112
113        mMountButton = (Button) findViewById(com.android.internal.R.id.mount_button);
114        mMountButton.setOnClickListener(this);
115        mUnmountButton = (Button) findViewById(com.android.internal.R.id.unmount_button);
116        mUnmountButton.setOnClickListener(this);
117        mProgressBar = (ProgressBar) findViewById(com.android.internal.R.id.progress);
118    }
119
120    private void switchDisplay(boolean usbStorageInUse) {
121        if (usbStorageInUse) {
122            mProgressBar.setVisibility(View.GONE);
123            mUnmountButton.setVisibility(View.VISIBLE);
124            mMountButton.setVisibility(View.GONE);
125            mIcon.setImageResource(com.android.internal.R.drawable.usb_android_connected);
126            mBanner.setText(com.android.internal.R.string.usb_storage_stop_title);
127            mMessage.setText(com.android.internal.R.string.usb_storage_stop_message);
128        } else {
129            mProgressBar.setVisibility(View.GONE);
130            mUnmountButton.setVisibility(View.GONE);
131            mMountButton.setVisibility(View.VISIBLE);
132            mIcon.setImageResource(com.android.internal.R.drawable.usb_android);
133            mBanner.setText(com.android.internal.R.string.usb_storage_title);
134            mMessage.setText(com.android.internal.R.string.usb_storage_message);
135        }
136    }
137
138    @Override
139    protected void onResume() {
140        super.onResume();
141
142        mStorageManager.registerListener(mStorageListener);
143        registerReceiver(mUsbStateReceiver, new IntentFilter(Usb.ACTION_USB_STATE));
144        try {
145            switchDisplay(mStorageManager.isUsbMassStorageEnabled());
146        } catch (Exception ex) {
147            Log.e(TAG, "Failed to read UMS enable state", ex);
148        }
149    }
150
151    @Override
152    protected void onPause() {
153        super.onPause();
154
155        unregisterReceiver(mUsbStateReceiver);
156        if (mStorageManager == null && mStorageListener != null) {
157            mStorageManager.unregisterListener(mStorageListener);
158        }
159    }
160
161    private void handleUsbStateChanged(Intent intent) {
162        boolean connected = intent.getExtras().getBoolean(Usb.USB_CONNECTED);
163        if (!connected) {
164            // It was disconnected from the plug, so finish
165            finish();
166        }
167    }
168
169    private IMountService getMountService() {
170        IBinder service = ServiceManager.getService("mount");
171        if (service != null) {
172            return IMountService.Stub.asInterface(service);
173        }
174        return null;
175    }
176
177    @Override
178    public Dialog onCreateDialog(int id, Bundle args) {
179        switch (id) {
180        case DLG_CONFIRM_KILL_STORAGE_USERS:
181            return new AlertDialog.Builder(this)
182                    .setTitle(R.string.dlg_confirm_kill_storage_users_title)
183                    .setPositiveButton(R.string.dlg_ok, new DialogInterface.OnClickListener() {
184                        public void onClick(DialogInterface dialog, int which) {
185                            switchUsbMassStorageAsync(true);
186                        }})
187                    .setNegativeButton(R.string.cancel, null)
188                    .setMessage(R.string.dlg_confirm_kill_storage_users_text)
189                    .setOnCancelListener(this)
190                    .create();
191        case DLG_ERROR_SHARING:
192            return new AlertDialog.Builder(this)
193                    .setTitle(R.string.dlg_error_title)
194                    .setNeutralButton(R.string.dlg_ok, null)
195                    .setMessage(R.string.usb_storage_error_message)
196                    .setOnCancelListener(this)
197                    .create();
198        }
199        return null;
200    }
201
202    private void showDialogInner(int id) {
203        removeDialog(id);
204        showDialog(id);
205    }
206
207    private void switchUsbMassStorageAsync(boolean on) {
208        mUnmountButton.setVisibility(View.GONE);
209        mMountButton.setVisibility(View.GONE);
210
211        mProgressBar.setVisibility(View.VISIBLE);
212        // will be hidden once USB mass storage kicks in (or fails)
213
214        final boolean _on = on;
215        new Thread() {
216            public void run() {
217                if (_on) {
218                    mStorageManager.enableUsbMassStorage();
219                } else {
220                    mStorageManager.disableUsbMassStorage();
221                }
222            }
223        }.start();
224    }
225
226    private void checkStorageUsers() {
227        IMountService ims = getMountService();
228        if (ims == null) {
229            // Display error dialog
230            showDialogInner(DLG_ERROR_SHARING);
231        }
232        String extStoragePath = Environment.getExternalStorageDirectory().toString();
233        boolean showDialog = false;
234        try {
235            int[] stUsers = ims.getStorageUsers(extStoragePath);
236            if (stUsers != null && stUsers.length > 0) {
237                showDialog = true;
238            } else {
239                // List of applications on sdcard.
240                ActivityManager am = (ActivityManager)getSystemService(Context.ACTIVITY_SERVICE);
241                List<ApplicationInfo> infoList = am.getRunningExternalApplications();
242                if (infoList != null && infoList.size() > 0) {
243                    showDialog = true;
244                }
245            }
246        } catch (RemoteException e) {
247            // Display error dialog
248            showDialogInner(DLG_ERROR_SHARING);
249        }
250        if (showDialog) {
251            // Display dialog to user
252            showDialogInner(DLG_CONFIRM_KILL_STORAGE_USERS);
253        } else {
254            if (localLOGV) Log.i(TAG, "Enabling UMS");
255            switchUsbMassStorageAsync(true);
256        }
257    }
258
259    public void onClick(View v) {
260        if (v == mMountButton) {
261           // Check for list of storage users and display dialog if needed.
262            checkStorageUsers();
263        } else if (v == mUnmountButton) {
264            if (localLOGV) Log.i(TAG, "Disabling UMS");
265            switchUsbMassStorageAsync(false);
266        }
267    }
268
269    public void onCancel(DialogInterface dialog) {
270        finish();
271    }
272
273}
274