blob: 0ed2a54bd1f409d4a76c9ffe3db1773ac7324fdc [file] [log] [blame]
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001/*
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
Joe Onoratofe4f3ae2010-06-04 11:25:26 -070017package com.android.systemui.usb;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080018
Daniel Sandlerb94f7952010-01-28 15:12:04 -050019import android.app.Activity;
Suchi Amalapurapuf7f5dda2010-03-23 10:34:28 -070020import android.app.ActivityManager;
Suchi Amalapurapu0eec21d2010-02-25 17:07:14 -080021import android.app.AlertDialog;
22import android.app.Dialog;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080023import android.content.BroadcastReceiver;
24import android.content.Context;
25import android.content.DialogInterface;
John Spurlockde84f0e2013-06-12 12:41:00 -040026import android.content.DialogInterface.OnCancelListener;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080027import android.content.Intent;
28import android.content.IntentFilter;
Suchi Amalapurapuf7f5dda2010-03-23 10:34:28 -070029import android.content.pm.ApplicationInfo;
Mike Lockwoodc4308f02011-03-01 08:04:54 -080030import android.hardware.usb.UsbManager;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080031import android.os.Bundle;
San Mehatec7f7e62010-01-29 05:34:01 -080032import android.os.Environment;
Daniel Sandlerc8b7b9f2010-03-16 16:01:29 -040033import android.os.Handler;
Daniel Sandler3a4940f2010-11-03 15:25:52 -040034import android.os.HandlerThread;
Suchi Amalapurapu0eec21d2010-02-25 17:07:14 -080035import android.os.IBinder;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080036import android.os.RemoteException;
37import android.os.ServiceManager;
John Spurlockde84f0e2013-06-12 12:41:00 -040038import android.os.storage.IMountService;
39import android.os.storage.StorageEventListener;
40import android.os.storage.StorageManager;
41import android.util.Log;
42import android.view.View;
43import android.view.WindowManager;
Daniel Sandlerb94f7952010-01-28 15:12:04 -050044import android.widget.Button;
John Spurlockde84f0e2013-06-12 12:41:00 -040045import android.widget.ImageView;
Daniel Sandlerc8b7b9f2010-03-16 16:01:29 -040046import android.widget.ProgressBar;
Daniel Sandlerb94f7952010-01-28 15:12:04 -050047import android.widget.TextView;
John Spurlockde84f0e2013-06-12 12:41:00 -040048
49import com.android.internal.R;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080050
Suchi Amalapurapuf7f5dda2010-03-23 10:34:28 -070051import java.util.List;
52
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080053/**
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 */
Suchi Amalapurapu0eec21d2010-02-25 17:07:14 -080058public class UsbStorageActivity extends Activity
59 implements View.OnClickListener, OnCancelListener {
San Mehatb1043402010-02-05 08:26:50 -080060 private static final String TAG = "UsbStorageActivity";
Daniel Sandlerc8b7b9f2010-03-16 16:01:29 -040061
Daniel Sandlerb94f7952010-01-28 15:12:04 -050062 private Button mMountButton;
63 private Button mUnmountButton;
Daniel Sandlerc8b7b9f2010-03-16 16:01:29 -040064 private ProgressBar mProgressBar;
Daniel Sandlerb94f7952010-01-28 15:12:04 -050065 private TextView mBanner;
66 private TextView mMessage;
67 private ImageView mIcon;
San Mehatb1043402010-02-05 08:26:50 -080068 private StorageManager mStorageManager = null;
Suchi Amalapurapu0eec21d2010-02-25 17:07:14 -080069 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;
Joe Onoratoc7f8b6f2011-02-03 17:44:47 -080072 private boolean mDestroyed;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080073
Daniel Sandler3a4940f2010-11-03 15:25:52 -040074 // UI thread
75 private Handler mUIHandler;
76
77 // thread for working with the storage services, which can be slow
78 private Handler mAsyncStorageHandler;
79
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080080 /** Used to detect when the USB cable is unplugged, so we can call finish() */
Mike Lockwood77bc30d2010-09-21 11:17:27 -040081 private BroadcastReceiver mUsbStateReceiver = new BroadcastReceiver() {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080082 @Override
83 public void onReceive(Context context, Intent intent) {
Mike Lockwood770126a2010-12-09 22:30:37 -080084 if (intent.getAction().equals(UsbManager.ACTION_USB_STATE)) {
Mike Lockwood77bc30d2010-09-21 11:17:27 -040085 handleUsbStateChanged(intent);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080086 }
87 }
88 };
San Mehatb1043402010-02-05 08:26:50 -080089
90 private StorageEventListener mStorageListener = new StorageEventListener() {
91 @Override
92 public void onStorageStateChanged(String path, String oldState, String newState) {
Daniel Sandlerc8b7b9f2010-03-16 16:01:29 -040093 final boolean on = newState.equals(Environment.MEDIA_SHARED);
94 switchDisplay(on);
San Mehatb1043402010-02-05 08:26:50 -080095 }
96 };
John Spurlock209bede2013-07-17 12:23:27 -040097
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080098 @Override
99 protected void onCreate(Bundle savedInstanceState) {
100 super.onCreate(savedInstanceState);
101
San Mehatb1043402010-02-05 08:26:50 -0800102 if (mStorageManager == null) {
103 mStorageManager = (StorageManager) getSystemService(Context.STORAGE_SERVICE);
104 if (mStorageManager == null) {
105 Log.w(TAG, "Failed to get StorageManager");
106 }
San Mehatb1043402010-02-05 08:26:50 -0800107 }
John Spurlock209bede2013-07-17 12:23:27 -0400108
Daniel Sandler3a4940f2010-11-03 15:25:52 -0400109 mUIHandler = new Handler();
110
111 HandlerThread thr = new HandlerThread("SystemUI UsbStorageActivity");
112 thr.start();
113 mAsyncStorageHandler = new Handler(thr.getLooper());
San Mehatb1043402010-02-05 08:26:50 -0800114
Dianne Hackborn20754642010-10-03 14:56:54 -0700115 getWindow().addFlags(WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD);
116 if (Environment.isExternalStorageRemovable()) {
117 getWindow().addFlags(WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED);
118 }
119
Daniel Sandlerb94f7952010-01-28 15:12:04 -0500120 setContentView(com.android.internal.R.layout.usb_storage_activity);
121
122 mIcon = (ImageView) findViewById(com.android.internal.R.id.icon);
123 mBanner = (TextView) findViewById(com.android.internal.R.id.banner);
124 mMessage = (TextView) findViewById(com.android.internal.R.id.message);
125
126 mMountButton = (Button) findViewById(com.android.internal.R.id.mount_button);
Suchi Amalapurapu0eec21d2010-02-25 17:07:14 -0800127 mMountButton.setOnClickListener(this);
Daniel Sandlerb94f7952010-01-28 15:12:04 -0500128 mUnmountButton = (Button) findViewById(com.android.internal.R.id.unmount_button);
Suchi Amalapurapu0eec21d2010-02-25 17:07:14 -0800129 mUnmountButton.setOnClickListener(this);
Daniel Sandlerc8b7b9f2010-03-16 16:01:29 -0400130 mProgressBar = (ProgressBar) findViewById(com.android.internal.R.id.progress);
Daniel Sandlerb94f7952010-01-28 15:12:04 -0500131 }
132
Joe Onoratoc7f8b6f2011-02-03 17:44:47 -0800133 @Override
134 protected void onDestroy() {
135 super.onDestroy();
136 mDestroyed = true;
137 }
138
Daniel Sandler3a4940f2010-11-03 15:25:52 -0400139 private void switchDisplay(final boolean usbStorageInUse) {
140 mUIHandler.post(new Runnable() {
141 @Override
142 public void run() {
143 switchDisplayAsync(usbStorageInUse);
144 }
145 });
146 }
147
148 private void switchDisplayAsync(boolean usbStorageInUse) {
Daniel Sandlerb94f7952010-01-28 15:12:04 -0500149 if (usbStorageInUse) {
Daniel Sandlerc8b7b9f2010-03-16 16:01:29 -0400150 mProgressBar.setVisibility(View.GONE);
Daniel Sandlerb94f7952010-01-28 15:12:04 -0500151 mUnmountButton.setVisibility(View.VISIBLE);
152 mMountButton.setVisibility(View.GONE);
153 mIcon.setImageResource(com.android.internal.R.drawable.usb_android_connected);
154 mBanner.setText(com.android.internal.R.string.usb_storage_stop_title);
155 mMessage.setText(com.android.internal.R.string.usb_storage_stop_message);
156 } else {
Daniel Sandlerc8b7b9f2010-03-16 16:01:29 -0400157 mProgressBar.setVisibility(View.GONE);
Daniel Sandlerb94f7952010-01-28 15:12:04 -0500158 mUnmountButton.setVisibility(View.GONE);
159 mMountButton.setVisibility(View.VISIBLE);
160 mIcon.setImageResource(com.android.internal.R.drawable.usb_android);
161 mBanner.setText(com.android.internal.R.string.usb_storage_title);
162 mMessage.setText(com.android.internal.R.string.usb_storage_message);
163 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800164 }
165
166 @Override
167 protected void onResume() {
168 super.onResume();
169
Suchi Amalapurapu0eec21d2010-02-25 17:07:14 -0800170 mStorageManager.registerListener(mStorageListener);
Mike Lockwood770126a2010-12-09 22:30:37 -0800171 registerReceiver(mUsbStateReceiver, new IntentFilter(UsbManager.ACTION_USB_STATE));
Daniel Sandlerb94f7952010-01-28 15:12:04 -0500172 try {
Daniel Sandler3a4940f2010-11-03 15:25:52 -0400173 mAsyncStorageHandler.post(new Runnable() {
174 @Override
175 public void run() {
176 switchDisplay(mStorageManager.isUsbMassStorageEnabled());
177 }
178 });
San Mehatb1043402010-02-05 08:26:50 -0800179 } catch (Exception ex) {
180 Log.e(TAG, "Failed to read UMS enable state", ex);
Daniel Sandlerb94f7952010-01-28 15:12:04 -0500181 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800182 }
183
184 @Override
185 protected void onPause() {
186 super.onPause();
John Spurlock209bede2013-07-17 12:23:27 -0400187
Mike Lockwood77bc30d2010-09-21 11:17:27 -0400188 unregisterReceiver(mUsbStateReceiver);
Suchi Amalapurapu0eec21d2010-02-25 17:07:14 -0800189 if (mStorageManager == null && mStorageListener != null) {
190 mStorageManager.unregisterListener(mStorageListener);
191 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800192 }
193
Mike Lockwood77bc30d2010-09-21 11:17:27 -0400194 private void handleUsbStateChanged(Intent intent) {
Mike Lockwood770126a2010-12-09 22:30:37 -0800195 boolean connected = intent.getExtras().getBoolean(UsbManager.USB_CONNECTED);
Mike Lockwood77bc30d2010-09-21 11:17:27 -0400196 if (!connected) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800197 // It was disconnected from the plug, so finish
198 finish();
199 }
200 }
Suchi Amalapurapu0eec21d2010-02-25 17:07:14 -0800201
202 private IMountService getMountService() {
203 IBinder service = ServiceManager.getService("mount");
204 if (service != null) {
205 return IMountService.Stub.asInterface(service);
206 }
207 return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800208 }
Suchi Amalapurapu0eec21d2010-02-25 17:07:14 -0800209
210 @Override
211 public Dialog onCreateDialog(int id, Bundle args) {
212 switch (id) {
213 case DLG_CONFIRM_KILL_STORAGE_USERS:
214 return new AlertDialog.Builder(this)
215 .setTitle(R.string.dlg_confirm_kill_storage_users_title)
216 .setPositiveButton(R.string.dlg_ok, new DialogInterface.OnClickListener() {
217 public void onClick(DialogInterface dialog, int which) {
Daniel Sandler3a4940f2010-11-03 15:25:52 -0400218 switchUsbMassStorage(true);
Suchi Amalapurapu0eec21d2010-02-25 17:07:14 -0800219 }})
220 .setNegativeButton(R.string.cancel, null)
221 .setMessage(R.string.dlg_confirm_kill_storage_users_text)
222 .setOnCancelListener(this)
223 .create();
224 case DLG_ERROR_SHARING:
225 return new AlertDialog.Builder(this)
226 .setTitle(R.string.dlg_error_title)
227 .setNeutralButton(R.string.dlg_ok, null)
228 .setMessage(R.string.usb_storage_error_message)
229 .setOnCancelListener(this)
230 .create();
231 }
232 return null;
233 }
234
Joe Onoratoc7f8b6f2011-02-03 17:44:47 -0800235 private void scheduleShowDialog(final int id) {
236 mUIHandler.post(new Runnable() {
237 @Override
238 public void run() {
239 if (!mDestroyed) {
240 removeDialog(id);
241 showDialog(id);
242 }
243 }
244 });
Suchi Amalapurapu0eec21d2010-02-25 17:07:14 -0800245 }
246
Daniel Sandler3a4940f2010-11-03 15:25:52 -0400247 private void switchUsbMassStorage(final boolean on) {
248 // things to do on the UI thread
249 mUIHandler.post(new Runnable() {
250 @Override
Daniel Sandlerc8b7b9f2010-03-16 16:01:29 -0400251 public void run() {
Daniel Sandler3a4940f2010-11-03 15:25:52 -0400252 mUnmountButton.setVisibility(View.GONE);
253 mMountButton.setVisibility(View.GONE);
254
255 mProgressBar.setVisibility(View.VISIBLE);
256 // will be hidden once USB mass storage kicks in (or fails)
257 }
258 });
John Spurlock209bede2013-07-17 12:23:27 -0400259
Daniel Sandler3a4940f2010-11-03 15:25:52 -0400260 // things to do elsewhere
261 mAsyncStorageHandler.post(new Runnable() {
262 @Override
263 public void run() {
264 if (on) {
Daniel Sandlerc8b7b9f2010-03-16 16:01:29 -0400265 mStorageManager.enableUsbMassStorage();
266 } else {
267 mStorageManager.disableUsbMassStorage();
268 }
269 }
Daniel Sandler3a4940f2010-11-03 15:25:52 -0400270 });
Daniel Sandlerc8b7b9f2010-03-16 16:01:29 -0400271 }
272
Suchi Amalapurapu0eec21d2010-02-25 17:07:14 -0800273 private void checkStorageUsers() {
Daniel Sandler3a4940f2010-11-03 15:25:52 -0400274 mAsyncStorageHandler.post(new Runnable() {
275 @Override
276 public void run() {
277 checkStorageUsersAsync();
278 }
279 });
280 }
281
282 private void checkStorageUsersAsync() {
Suchi Amalapurapu0eec21d2010-02-25 17:07:14 -0800283 IMountService ims = getMountService();
284 if (ims == null) {
285 // Display error dialog
Joe Onoratoc7f8b6f2011-02-03 17:44:47 -0800286 scheduleShowDialog(DLG_ERROR_SHARING);
Suchi Amalapurapu0eec21d2010-02-25 17:07:14 -0800287 }
Suchi Amalapurapuf7f5dda2010-03-23 10:34:28 -0700288 String extStoragePath = Environment.getExternalStorageDirectory().toString();
289 boolean showDialog = false;
Suchi Amalapurapu0eec21d2010-02-25 17:07:14 -0800290 try {
Suchi Amalapurapuf7f5dda2010-03-23 10:34:28 -0700291 int[] stUsers = ims.getStorageUsers(extStoragePath);
292 if (stUsers != null && stUsers.length > 0) {
293 showDialog = true;
294 } else {
295 // List of applications on sdcard.
296 ActivityManager am = (ActivityManager)getSystemService(Context.ACTIVITY_SERVICE);
297 List<ApplicationInfo> infoList = am.getRunningExternalApplications();
298 if (infoList != null && infoList.size() > 0) {
299 showDialog = true;
300 }
301 }
Suchi Amalapurapu0eec21d2010-02-25 17:07:14 -0800302 } catch (RemoteException e) {
Suchi Amalapurapuf7f5dda2010-03-23 10:34:28 -0700303 // Display error dialog
Joe Onoratoc7f8b6f2011-02-03 17:44:47 -0800304 scheduleShowDialog(DLG_ERROR_SHARING);
Suchi Amalapurapu0eec21d2010-02-25 17:07:14 -0800305 }
Suchi Amalapurapuf7f5dda2010-03-23 10:34:28 -0700306 if (showDialog) {
Suchi Amalapurapu0eec21d2010-02-25 17:07:14 -0800307 // Display dialog to user
Joe Onoratoc7f8b6f2011-02-03 17:44:47 -0800308 scheduleShowDialog(DLG_CONFIRM_KILL_STORAGE_USERS);
Suchi Amalapurapu0eec21d2010-02-25 17:07:14 -0800309 } else {
310 if (localLOGV) Log.i(TAG, "Enabling UMS");
Daniel Sandler3a4940f2010-11-03 15:25:52 -0400311 switchUsbMassStorage(true);
Suchi Amalapurapu0eec21d2010-02-25 17:07:14 -0800312 }
313 }
314
315 public void onClick(View v) {
Suchi Amalapurapu0eec21d2010-02-25 17:07:14 -0800316 if (v == mMountButton) {
317 // Check for list of storage users and display dialog if needed.
318 checkStorageUsers();
319 } else if (v == mUnmountButton) {
320 if (localLOGV) Log.i(TAG, "Disabling UMS");
Daniel Sandler3a4940f2010-11-03 15:25:52 -0400321 switchUsbMassStorage(false);
Suchi Amalapurapu0eec21d2010-02-25 17:07:14 -0800322 }
323 }
324
325 public void onCancel(DialogInterface dialog) {
326 finish();
Daniel Sandlerb94f7952010-01-28 15:12:04 -0500327 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800328
329}