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