USB connected notification and temporary USB options dialog

This change adds a notification when USB is connected.
Selecting the notification brings up a dialog to allow switching between
MTP and PTP modes, and also allows mounting a CD image for installing AFT.
The UI design is not final - this is a temporary implementation of the UI.

Change-Id: Idd678537aba595fd4cb183ea755bf437f372d826
Signed-off-by: Mike Lockwood <lockwood@android.com>
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index d9e7dac..b5f4084 100755
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -2608,6 +2608,11 @@
     <!-- USB_STORAGE_ERROR dialog  ok button-->
     <string name="dlg_ok">OK</string>
 
+    <!-- USB_PREFERENCES: When the user connects the phone to a computer via USB, we show a notification asking if he wants to share files across.  This is the title -->
+    <string name="usb_preferences_notification_title">USB connected</string>
+    <!-- See USB_PREFERENCES. This is the message. -->
+    <string name="usb_preferece_notification_message">Select to configure USB file transfer.</string>
+
     <!-- External media format dialog strings -->
     <!-- This is the label for the activity, and should never be visible to the user. -->
     <!-- See EXTMEDIA_FORMAT.  EXTMEDIA_FORMAT_DIALOG:  After the user selects the notification, a dialog is shown asking if he wants to format the SD card.  This is the title. [CHAR LIMIT=20] -->
diff --git a/packages/SystemUI/AndroidManifest.xml b/packages/SystemUI/AndroidManifest.xml
index 55f5280..6d8eab6 100644
--- a/packages/SystemUI/AndroidManifest.xml
+++ b/packages/SystemUI/AndroidManifest.xml
@@ -25,6 +25,10 @@
             android:exported="true"
             />
 
+        <activity android:name=".usb.UsbPreferenceActivity"
+             android:theme="@*android:style/Theme.Holo.Dialog.Alert"
+             android:excludeFromRecents="true">
+        </activity>
         <activity android:name=".usb.UsbStorageActivity"
                 android:excludeFromRecents="true">
         </activity>
diff --git a/packages/SystemUI/res/layout/usb_preference_buttons.xml b/packages/SystemUI/res/layout/usb_preference_buttons.xml
new file mode 100644
index 0000000..babe07e
--- /dev/null
+++ b/packages/SystemUI/res/layout/usb_preference_buttons.xml
@@ -0,0 +1,43 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2008 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<!-- Check box that is displayed in the activity resolver UI for the user
+     to make their selection the preferred activity. -->
+<LinearLayout
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent"
+    android:layout_height="wrap_content"
+    android:paddingLeft="14dip"
+    android:paddingRight="15dip"
+    android:orientation="vertical">
+
+    <Button
+        android:id="@+id/mtp_ptp_button"
+        android:text="@string/use_ptp_button_title"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:focusable="true"
+        android:clickable="true" />
+
+    <Button
+        android:id="@+id/installer_cd_button"
+        android:text="@string/installer_cd_button_title"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:focusable="true"
+        android:clickable="true" />
+
+</LinearLayout>
diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml
index 8945da5..86e0cd0 100644
--- a/packages/SystemUI/res/values/strings.xml
+++ b/packages/SystemUI/res/values/strings.xml
@@ -156,4 +156,13 @@
 
     <!-- Compatibility mode help screen: body text. [CHAR LIMIT=150] -->
     <string name="compat_mode_help_body">When an app was designed for a smaller screen, a zoom control will appear by the clock.</string>
+
+    <!-- Title for the USB function chooser in UsbPreferenceActivity. [CHAR LIMIT=30] -->
+    <string name="usb_preference_title">USB file transfer options</string>
+    <!-- Label for the MTP USB function in UsbPreferenceActivity. [CHAR LIMIT=50] -->
+    <string name="use_mtp_button_title">Mount as a media player (MTP)</string>
+    <!-- Label for the PTP USB function in UsbPreferenceActivity. [CHAR LIMIT=50] -->
+    <string name="use_ptp_button_title">Mount as a camera (PTP)</string>
+    <!-- Label for the installer CD image option in UsbPreferenceActivity. [CHAR LIMIT=50] -->
+    <string name="installer_cd_button_title">Install Android File Transfer application for Mac</string>
 </resources>
diff --git a/packages/SystemUI/src/com/android/systemui/usb/UsbPreferenceActivity.java b/packages/SystemUI/src/com/android/systemui/usb/UsbPreferenceActivity.java
new file mode 100644
index 0000000..3ed44e8
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/usb/UsbPreferenceActivity.java
@@ -0,0 +1,91 @@
+/*

+ * Copyright (C) 2011 The Android Open Source Project

+ *

+ * Licensed under the Apache License, Version 2.0 (the "License");

+ * you may not use this file except in compliance with the License.

+ * You may obtain a copy of the License at

+ *

+ *      http://www.apache.org/licenses/LICENSE-2.0

+ *

+ * Unless required by applicable law or agreed to in writing, software

+ * distributed under the License is distributed on an "AS IS" BASIS,

+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.

+ * See the License for the specific language governing permissions and

+ * limitations under the License.

+ */

+

+package com.android.systemui.usb;

+

+import android.app.Activity;

+import android.app.AlertDialog;

+import android.content.Context;

+import android.content.DialogInterface;

+import android.hardware.usb.UsbManager;

+import android.os.Bundle;

+import android.view.LayoutInflater;

+import android.view.View;

+import android.util.Log;

+import android.widget.Button;

+

+import java.io.File;

+

+import com.android.systemui.R;

+

+public class UsbPreferenceActivity extends Activity implements View.OnClickListener  {

+

+    private static final String TAG = "UsbPreferenceActivity";

+

+    private UsbManager mUsbManager;

+    private String mCurrentFunction;

+    private String[] mFunctions;

+    private String mInstallerImagePath;

+    private Button mMtpPtpButton;

+    private Button mInstallerCdButton;

+    private boolean mPtpActive;

+

+    @Override

+    public void onCreate(Bundle icicle) {

+        super.onCreate(icicle);

+

+        mUsbManager = (UsbManager)getSystemService(Context.USB_SERVICE);

+

+        AlertDialog.Builder dialogBuilder = new AlertDialog.Builder(this);

+        dialogBuilder.setTitle(getString(R.string.usb_preference_title));

+

+        LayoutInflater inflater = (LayoutInflater)getSystemService(

+                Context.LAYOUT_INFLATER_SERVICE);

+        View buttonView = inflater.inflate(R.layout.usb_preference_buttons, null);

+        dialogBuilder.setView(buttonView);

+        mMtpPtpButton = (Button)buttonView.findViewById(R.id.mtp_ptp_button);

+        mInstallerCdButton = (Button)buttonView.findViewById(R.id.installer_cd_button);

+        mMtpPtpButton.setOnClickListener(this);

+        mInstallerCdButton.setOnClickListener(this);

+

+        mPtpActive = mUsbManager.isFunctionEnabled(UsbManager.USB_FUNCTION_PTP);

+        if (mPtpActive) {

+            mMtpPtpButton.setText(R.string.use_mtp_button_title);

+        }

+

+        mInstallerImagePath = getString(com.android.internal.R.string.config_isoImagePath);

+        if (!(new File(mInstallerImagePath)).exists()) {

+            mInstallerCdButton.setVisibility(View.GONE);

+        }

+

+        dialogBuilder.show();

+    }

+

+    public void onClick(View v) {

+        if (v.equals(mMtpPtpButton)) {

+            if (mPtpActive) {

+                mUsbManager.setPrimaryFunction(UsbManager.USB_FUNCTION_MTP);

+            } else {

+                mUsbManager.setPrimaryFunction(UsbManager.USB_FUNCTION_PTP);

+            }

+        } else if (v.equals(mInstallerCdButton)) {

+            mUsbManager.setPrimaryFunction(UsbManager.USB_FUNCTION_MASS_STORAGE);

+            mUsbManager.setMassStorageBackingFile(mInstallerImagePath);

+        }

+

+        finish();

+    }

+}

diff --git a/services/java/com/android/server/usb/UsbDeviceManager.java b/services/java/com/android/server/usb/UsbDeviceManager.java
index e03f9a0..b7f9d5c 100644
--- a/services/java/com/android/server/usb/UsbDeviceManager.java
+++ b/services/java/com/android/server/usb/UsbDeviceManager.java
@@ -95,11 +95,17 @@
     private NotificationManager mNotificationManager;
     private final boolean mHasUsbAccessory;
 
-    // for adb connected notifications
+    // for USB connected notification
+    private boolean mUsbNotificationShown;
+    private boolean mUseUsbNotification;
+    private Notification mUsbNotification;
+
+    // for adb connected notification
     private boolean mAdbNotificationShown;
     private Notification mAdbNotification;
     private boolean mAdbEnabled;
 
+
     private class AdbSettingsObserver extends ContentObserver {
         public AdbSettingsObserver() {
             super(null);
@@ -112,6 +118,50 @@
         }
     }
 
+    private void updateUsbNotification(boolean connected) {
+        if (mNotificationManager == null || !mUseUsbNotification) return;
+        if (connected) {
+            if (!mUsbNotificationShown) {
+                Resources r = mContext.getResources();
+                CharSequence title = r.getText(
+                        com.android.internal.R.string.usb_preferences_notification_title);
+                CharSequence message = r.getText(
+                        com.android.internal.R.string.usb_preferece_notification_message);
+
+                if (mUsbNotification == null) {
+                    mUsbNotification = new Notification();
+                    mUsbNotification.icon = com.android.internal.R.drawable.stat_sys_data_usb;
+                    mUsbNotification.when = 0;
+                    mUsbNotification.flags = Notification.FLAG_ONGOING_EVENT;
+                    mUsbNotification.tickerText = title;
+                    mUsbNotification.defaults = 0; // please be quiet
+                    mUsbNotification.sound = null;
+                    mUsbNotification.vibrate = null;
+                }
+
+                Intent intent = new Intent();
+                intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK |
+                        Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED);
+                intent.setClassName("com.android.systemui",
+                        "com.android.systemui.usb.UsbPreferenceActivity");
+                PendingIntent pi = PendingIntent.getActivity(mContext, 0,
+                        intent, 0);
+
+                mUsbNotification.setLatestEventInfo(mContext, title, message, pi);
+
+                mUsbNotificationShown = true;
+                mNotificationManager.notify(
+                        com.android.internal.R.string.usb_preferences_notification_title,
+                        mUsbNotification);
+            }
+
+        } else if (mUsbNotificationShown) {
+            mUsbNotificationShown = false;
+            mNotificationManager.cancel(
+                    com.android.internal.R.string.usb_preferences_notification_title);
+        }
+    }
+
     private void updateAdbNotification(boolean adbEnabled) {
         if (mNotificationManager == null) return;
         if (adbEnabled) {
@@ -205,6 +255,17 @@
         mNotificationManager = (NotificationManager)
                 mContext.getSystemService(Context.NOTIFICATION_SERVICE);
 
+        // We do not show the USB notification if the primary volume supports mass storage.
+        // The legacy mass storage UI will be used instead.
+        boolean massStorageSupported = false;
+        StorageManager storageManager = (StorageManager)
+                mContext.getSystemService(Context.STORAGE_SERVICE);
+        StorageVolume[] volumes = storageManager.getVolumeList();
+        if (volumes.length > 0) {
+            massStorageSupported = volumes[0].allowMassStorage();
+        }
+        mUseUsbNotification = !massStorageSupported;
+
         // make sure the ADB_ENABLED setting value matches the current state
         Settings.Secure.putInt(mContentResolver, Settings.Secure.ADB_ENABLED, mAdbEnabled ? 1 : 0);
 
@@ -448,6 +509,7 @@
                 case MSG_UPDATE_STATE:
                     mConnected = (msg.arg1 == 1);
                     mConfigured = (msg.arg2 == 1);
+                    updateUsbNotification(mConnected);
                     updateAdbNotification(mAdbEnabled && mConnected);
                     if (containsFunction(mCurrentFunctions,
                             UsbManager.USB_FUNCTION_ACCESSORY)) {
@@ -481,6 +543,7 @@
                     mDefaultFunctions = function;
                     break;
                 case MSG_SYSTEM_READY:
+                    updateUsbNotification(mConnected);
                     updateAdbNotification(mAdbEnabled && mConnected);
                     updateUsbState();
                     if (mCurrentAccessory != null && mDeferAccessoryAttached) {