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