blob: e61ef8ada9ed3e43edb60a80dfdac80b2561c369 [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
Suchi Amalapurapu0eec21d2010-02-25 17:07:14 -080019import com.android.internal.R;
Daniel Sandlerb94f7952010-01-28 15:12:04 -050020import android.app.Activity;
Suchi Amalapurapuf7f5dda2010-03-23 10:34:28 -070021import android.app.ActivityManager;
Suchi Amalapurapu0eec21d2010-02-25 17:07:14 -080022import android.app.AlertDialog;
23import android.app.Dialog;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080024import android.content.BroadcastReceiver;
25import android.content.Context;
26import android.content.DialogInterface;
27import android.content.Intent;
28import android.content.IntentFilter;
Suchi Amalapurapu0eec21d2010-02-25 17:07:14 -080029import android.content.DialogInterface.OnCancelListener;
Suchi Amalapurapuf7f5dda2010-03-23 10:34:28 -070030import android.content.pm.ApplicationInfo;
31import android.content.pm.PackageManager;
32import android.content.pm.PackageManager.NameNotFoundException;
Mike Lockwoodc4308f02011-03-01 08:04:54 -080033import android.hardware.usb.UsbManager;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080034import android.os.Bundle;
San Mehatec7f7e62010-01-29 05:34:01 -080035import android.os.Environment;
Daniel Sandlerc8b7b9f2010-03-16 16:01:29 -040036import android.os.Handler;
Daniel Sandler3a4940f2010-11-03 15:25:52 -040037import android.os.HandlerThread;
Suchi Amalapurapu0eec21d2010-02-25 17:07:14 -080038import android.os.IBinder;
39import android.os.storage.IMountService;
San Mehatb1043402010-02-05 08:26:50 -080040import android.os.storage.StorageManager;
41import android.os.storage.StorageEventListener;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080042import android.os.RemoteException;
43import android.os.ServiceManager;
Daniel Sandlerb94f7952010-01-28 15:12:04 -050044import android.widget.ImageView;
45import android.widget.Button;
Daniel Sandlerc8b7b9f2010-03-16 16:01:29 -040046import android.widget.ProgressBar;
Daniel Sandlerb94f7952010-01-28 15:12:04 -050047import android.widget.TextView;
Daniel Sandlerb94f7952010-01-28 15:12:04 -050048import android.view.View;
Daniel Sandlerc8b7b9f2010-03-16 16:01:29 -040049import android.view.Window;
Dianne Hackborn20754642010-10-03 14:56:54 -070050import android.view.WindowManager;
San Mehatb1043402010-02-05 08:26:50 -080051import android.util.Log;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080052
Suchi Amalapurapuf7f5dda2010-03-23 10:34:28 -070053import java.util.List;
54
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080055/**
56 * This activity is shown to the user for him/her to enable USB mass storage
57 * on-demand (that is, when the USB cable is connected). It uses the alert
58 * dialog style. It will be launched from a notification.
59 */
Suchi Amalapurapu0eec21d2010-02-25 17:07:14 -080060public class UsbStorageActivity extends Activity
61 implements View.OnClickListener, OnCancelListener {
San Mehatb1043402010-02-05 08:26:50 -080062 private static final String TAG = "UsbStorageActivity";
Daniel Sandlerc8b7b9f2010-03-16 16:01:29 -040063
Daniel Sandlerb94f7952010-01-28 15:12:04 -050064 private Button mMountButton;
65 private Button mUnmountButton;
Daniel Sandlerc8b7b9f2010-03-16 16:01:29 -040066 private ProgressBar mProgressBar;
Daniel Sandlerb94f7952010-01-28 15:12:04 -050067 private TextView mBanner;
68 private TextView mMessage;
69 private ImageView mIcon;
San Mehatb1043402010-02-05 08:26:50 -080070 private StorageManager mStorageManager = null;
Suchi Amalapurapu0eec21d2010-02-25 17:07:14 -080071 private static final int DLG_CONFIRM_KILL_STORAGE_USERS = 1;
72 private static final int DLG_ERROR_SHARING = 2;
73 static final boolean localLOGV = false;
Joe Onoratoc7f8b6f2011-02-03 17:44:47 -080074 private boolean mDestroyed;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080075
Daniel Sandler3a4940f2010-11-03 15:25:52 -040076 // UI thread
77 private Handler mUIHandler;
78
79 // thread for working with the storage services, which can be slow
80 private Handler mAsyncStorageHandler;
81
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080082 /** Used to detect when the USB cable is unplugged, so we can call finish() */
Mike Lockwood77bc30d2010-09-21 11:17:27 -040083 private BroadcastReceiver mUsbStateReceiver = new BroadcastReceiver() {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080084 @Override
85 public void onReceive(Context context, Intent intent) {
Mike Lockwood770126a2010-12-09 22:30:37 -080086 if (intent.getAction().equals(UsbManager.ACTION_USB_STATE)) {
Mike Lockwood77bc30d2010-09-21 11:17:27 -040087 handleUsbStateChanged(intent);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080088 }
89 }
90 };
San Mehatb1043402010-02-05 08:26:50 -080091
92 private StorageEventListener mStorageListener = new StorageEventListener() {
93 @Override
94 public void onStorageStateChanged(String path, String oldState, String newState) {
Daniel Sandlerc8b7b9f2010-03-16 16:01:29 -040095 final boolean on = newState.equals(Environment.MEDIA_SHARED);
96 switchDisplay(on);
San Mehatb1043402010-02-05 08:26:50 -080097 }
98 };
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080099
100 @Override
101 protected void onCreate(Bundle savedInstanceState) {
102 super.onCreate(savedInstanceState);
103
San Mehatb1043402010-02-05 08:26:50 -0800104 if (mStorageManager == null) {
105 mStorageManager = (StorageManager) getSystemService(Context.STORAGE_SERVICE);
106 if (mStorageManager == null) {
107 Log.w(TAG, "Failed to get StorageManager");
108 }
San Mehatb1043402010-02-05 08:26:50 -0800109 }
Daniel Sandler3a4940f2010-11-03 15:25:52 -0400110
111 mUIHandler = new Handler();
112
113 HandlerThread thr = new HandlerThread("SystemUI UsbStorageActivity");
114 thr.start();
115 mAsyncStorageHandler = new Handler(thr.getLooper());
San Mehatb1043402010-02-05 08:26:50 -0800116
Dianne Hackborn20754642010-10-03 14:56:54 -0700117 getWindow().addFlags(WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD);
118 if (Environment.isExternalStorageRemovable()) {
119 getWindow().addFlags(WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED);
120 }
121
Daniel Sandlerb94f7952010-01-28 15:12:04 -0500122 setContentView(com.android.internal.R.layout.usb_storage_activity);
123
124 mIcon = (ImageView) findViewById(com.android.internal.R.id.icon);
125 mBanner = (TextView) findViewById(com.android.internal.R.id.banner);
126 mMessage = (TextView) findViewById(com.android.internal.R.id.message);
127
128 mMountButton = (Button) findViewById(com.android.internal.R.id.mount_button);
Suchi Amalapurapu0eec21d2010-02-25 17:07:14 -0800129 mMountButton.setOnClickListener(this);
Daniel Sandlerb94f7952010-01-28 15:12:04 -0500130 mUnmountButton = (Button) findViewById(com.android.internal.R.id.unmount_button);
Suchi Amalapurapu0eec21d2010-02-25 17:07:14 -0800131 mUnmountButton.setOnClickListener(this);
Daniel Sandlerc8b7b9f2010-03-16 16:01:29 -0400132 mProgressBar = (ProgressBar) findViewById(com.android.internal.R.id.progress);
Daniel Sandlerb94f7952010-01-28 15:12:04 -0500133 }
134
Joe Onoratoc7f8b6f2011-02-03 17:44:47 -0800135 @Override
136 protected void onDestroy() {
137 super.onDestroy();
138 mDestroyed = true;
139 }
140
Daniel Sandler3a4940f2010-11-03 15:25:52 -0400141 private void switchDisplay(final boolean usbStorageInUse) {
142 mUIHandler.post(new Runnable() {
143 @Override
144 public void run() {
145 switchDisplayAsync(usbStorageInUse);
146 }
147 });
148 }
149
150 private void switchDisplayAsync(boolean usbStorageInUse) {
Daniel Sandlerb94f7952010-01-28 15:12:04 -0500151 if (usbStorageInUse) {
Daniel Sandlerc8b7b9f2010-03-16 16:01:29 -0400152 mProgressBar.setVisibility(View.GONE);
Daniel Sandlerb94f7952010-01-28 15:12:04 -0500153 mUnmountButton.setVisibility(View.VISIBLE);
154 mMountButton.setVisibility(View.GONE);
155 mIcon.setImageResource(com.android.internal.R.drawable.usb_android_connected);
156 mBanner.setText(com.android.internal.R.string.usb_storage_stop_title);
157 mMessage.setText(com.android.internal.R.string.usb_storage_stop_message);
158 } else {
Daniel Sandlerc8b7b9f2010-03-16 16:01:29 -0400159 mProgressBar.setVisibility(View.GONE);
Daniel Sandlerb94f7952010-01-28 15:12:04 -0500160 mUnmountButton.setVisibility(View.GONE);
161 mMountButton.setVisibility(View.VISIBLE);
162 mIcon.setImageResource(com.android.internal.R.drawable.usb_android);
163 mBanner.setText(com.android.internal.R.string.usb_storage_title);
164 mMessage.setText(com.android.internal.R.string.usb_storage_message);
165 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800166 }
167
168 @Override
169 protected void onResume() {
170 super.onResume();
171
Suchi Amalapurapu0eec21d2010-02-25 17:07:14 -0800172 mStorageManager.registerListener(mStorageListener);
Mike Lockwood770126a2010-12-09 22:30:37 -0800173 registerReceiver(mUsbStateReceiver, new IntentFilter(UsbManager.ACTION_USB_STATE));
Daniel Sandlerb94f7952010-01-28 15:12:04 -0500174 try {
Daniel Sandler3a4940f2010-11-03 15:25:52 -0400175 mAsyncStorageHandler.post(new Runnable() {
176 @Override
177 public void run() {
178 switchDisplay(mStorageManager.isUsbMassStorageEnabled());
179 }
180 });
San Mehatb1043402010-02-05 08:26:50 -0800181 } catch (Exception ex) {
182 Log.e(TAG, "Failed to read UMS enable state", ex);
Daniel Sandlerb94f7952010-01-28 15:12:04 -0500183 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800184 }
185
186 @Override
187 protected void onPause() {
188 super.onPause();
189
Mike Lockwood77bc30d2010-09-21 11:17:27 -0400190 unregisterReceiver(mUsbStateReceiver);
Suchi Amalapurapu0eec21d2010-02-25 17:07:14 -0800191 if (mStorageManager == null && mStorageListener != null) {
192 mStorageManager.unregisterListener(mStorageListener);
193 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800194 }
195
Mike Lockwood77bc30d2010-09-21 11:17:27 -0400196 private void handleUsbStateChanged(Intent intent) {
Mike Lockwood770126a2010-12-09 22:30:37 -0800197 boolean connected = intent.getExtras().getBoolean(UsbManager.USB_CONNECTED);
Mike Lockwood77bc30d2010-09-21 11:17:27 -0400198 if (!connected) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800199 // It was disconnected from the plug, so finish
200 finish();
201 }
202 }
Suchi Amalapurapu0eec21d2010-02-25 17:07:14 -0800203
204 private IMountService getMountService() {
205 IBinder service = ServiceManager.getService("mount");
206 if (service != null) {
207 return IMountService.Stub.asInterface(service);
208 }
209 return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800210 }
Suchi Amalapurapu0eec21d2010-02-25 17:07:14 -0800211
212 @Override
213 public Dialog onCreateDialog(int id, Bundle args) {
214 switch (id) {
215 case DLG_CONFIRM_KILL_STORAGE_USERS:
216 return new AlertDialog.Builder(this)
217 .setTitle(R.string.dlg_confirm_kill_storage_users_title)
218 .setPositiveButton(R.string.dlg_ok, new DialogInterface.OnClickListener() {
219 public void onClick(DialogInterface dialog, int which) {
Daniel Sandler3a4940f2010-11-03 15:25:52 -0400220 switchUsbMassStorage(true);
Suchi Amalapurapu0eec21d2010-02-25 17:07:14 -0800221 }})
222 .setNegativeButton(R.string.cancel, null)
223 .setMessage(R.string.dlg_confirm_kill_storage_users_text)
224 .setOnCancelListener(this)
225 .create();
226 case DLG_ERROR_SHARING:
227 return new AlertDialog.Builder(this)
228 .setTitle(R.string.dlg_error_title)
229 .setNeutralButton(R.string.dlg_ok, null)
230 .setMessage(R.string.usb_storage_error_message)
231 .setOnCancelListener(this)
232 .create();
233 }
234 return null;
235 }
236
Joe Onoratoc7f8b6f2011-02-03 17:44:47 -0800237 private void scheduleShowDialog(final int id) {
238 mUIHandler.post(new Runnable() {
239 @Override
240 public void run() {
241 if (!mDestroyed) {
242 removeDialog(id);
243 showDialog(id);
244 }
245 }
246 });
Suchi Amalapurapu0eec21d2010-02-25 17:07:14 -0800247 }
248
Daniel Sandler3a4940f2010-11-03 15:25:52 -0400249 private void switchUsbMassStorage(final boolean on) {
250 // things to do on the UI thread
251 mUIHandler.post(new Runnable() {
252 @Override
Daniel Sandlerc8b7b9f2010-03-16 16:01:29 -0400253 public void run() {
Daniel Sandler3a4940f2010-11-03 15:25:52 -0400254 mUnmountButton.setVisibility(View.GONE);
255 mMountButton.setVisibility(View.GONE);
256
257 mProgressBar.setVisibility(View.VISIBLE);
258 // will be hidden once USB mass storage kicks in (or fails)
259 }
260 });
261
262 // things to do elsewhere
263 mAsyncStorageHandler.post(new Runnable() {
264 @Override
265 public void run() {
266 if (on) {
Daniel Sandlerc8b7b9f2010-03-16 16:01:29 -0400267 mStorageManager.enableUsbMassStorage();
268 } else {
269 mStorageManager.disableUsbMassStorage();
270 }
271 }
Daniel Sandler3a4940f2010-11-03 15:25:52 -0400272 });
Daniel Sandlerc8b7b9f2010-03-16 16:01:29 -0400273 }
274
Suchi Amalapurapu0eec21d2010-02-25 17:07:14 -0800275 private void checkStorageUsers() {
Daniel Sandler3a4940f2010-11-03 15:25:52 -0400276 mAsyncStorageHandler.post(new Runnable() {
277 @Override
278 public void run() {
279 checkStorageUsersAsync();
280 }
281 });
282 }
283
284 private void checkStorageUsersAsync() {
Suchi Amalapurapu0eec21d2010-02-25 17:07:14 -0800285 IMountService ims = getMountService();
286 if (ims == null) {
287 // Display error dialog
Joe Onoratoc7f8b6f2011-02-03 17:44:47 -0800288 scheduleShowDialog(DLG_ERROR_SHARING);
Suchi Amalapurapu0eec21d2010-02-25 17:07:14 -0800289 }
Suchi Amalapurapuf7f5dda2010-03-23 10:34:28 -0700290 String extStoragePath = Environment.getExternalStorageDirectory().toString();
291 boolean showDialog = false;
Suchi Amalapurapu0eec21d2010-02-25 17:07:14 -0800292 try {
Suchi Amalapurapuf7f5dda2010-03-23 10:34:28 -0700293 int[] stUsers = ims.getStorageUsers(extStoragePath);
294 if (stUsers != null && stUsers.length > 0) {
295 showDialog = true;
296 } else {
297 // List of applications on sdcard.
298 ActivityManager am = (ActivityManager)getSystemService(Context.ACTIVITY_SERVICE);
299 List<ApplicationInfo> infoList = am.getRunningExternalApplications();
300 if (infoList != null && infoList.size() > 0) {
301 showDialog = true;
302 }
303 }
Suchi Amalapurapu0eec21d2010-02-25 17:07:14 -0800304 } catch (RemoteException e) {
Suchi Amalapurapuf7f5dda2010-03-23 10:34:28 -0700305 // Display error dialog
Joe Onoratoc7f8b6f2011-02-03 17:44:47 -0800306 scheduleShowDialog(DLG_ERROR_SHARING);
Suchi Amalapurapu0eec21d2010-02-25 17:07:14 -0800307 }
Suchi Amalapurapuf7f5dda2010-03-23 10:34:28 -0700308 if (showDialog) {
Suchi Amalapurapu0eec21d2010-02-25 17:07:14 -0800309 // Display dialog to user
Joe Onoratoc7f8b6f2011-02-03 17:44:47 -0800310 scheduleShowDialog(DLG_CONFIRM_KILL_STORAGE_USERS);
Suchi Amalapurapu0eec21d2010-02-25 17:07:14 -0800311 } else {
312 if (localLOGV) Log.i(TAG, "Enabling UMS");
Daniel Sandler3a4940f2010-11-03 15:25:52 -0400313 switchUsbMassStorage(true);
Suchi Amalapurapu0eec21d2010-02-25 17:07:14 -0800314 }
315 }
316
317 public void onClick(View v) {
Suchi Amalapurapu0eec21d2010-02-25 17:07:14 -0800318 if (v == mMountButton) {
319 // Check for list of storage users and display dialog if needed.
320 checkStorageUsers();
321 } else if (v == mUnmountButton) {
322 if (localLOGV) Log.i(TAG, "Disabling UMS");
Daniel Sandler3a4940f2010-11-03 15:25:52 -0400323 switchUsbMassStorage(false);
Suchi Amalapurapu0eec21d2010-02-25 17:07:14 -0800324 }
325 }
326
327 public void onCancel(DialogInterface dialog) {
328 finish();
Daniel Sandlerb94f7952010-01-28 15:12:04 -0500329 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800330
331}