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