Adds package picker for sending text messages.

Bug: 10608694
Change-Id: I645f00135615d29b78e72b80584fea0410d7da8d
diff --git a/src/com/android/phone/CallCommandService.java b/src/com/android/phone/CallCommandService.java
index 371ca7b..04c26d0 100644
--- a/src/com/android/phone/CallCommandService.java
+++ b/src/com/android/phone/CallCommandService.java
@@ -80,14 +80,13 @@
             CallResult result = mCallModeler.getCallWithId(callId);
             if (result != null) {
                 final String number = result.getConnection().getAddress();
+
                 Log.v(TAG, "Hanging up");
                 PhoneUtils.hangupRingingCall(result.getConnection().getCall());
+
                 if (rejectWithMessage) {
-                    if (message != null) {
-                        mRejectWithTextMessageManager.rejectCallWithMessage(number, message);
-                    } else {
-                        mRejectWithTextMessageManager.rejectCallWithNewMessage(number);
-                    }
+                    mRejectWithTextMessageManager.rejectCallWithMessage(
+                            result.getConnection().getCall(), message);
                 }
             }
         } catch (Exception e) {
diff --git a/src/com/android/phone/PhoneGlobals.java b/src/com/android/phone/PhoneGlobals.java
index dc7d64b..db06c30 100644
--- a/src/com/android/phone/PhoneGlobals.java
+++ b/src/com/android/phone/PhoneGlobals.java
@@ -1034,16 +1034,12 @@
         //
         boolean isRinging = (state == PhoneConstants.State.RINGING);
         boolean isDialing = (phone.getForegroundCall().getState() == Call.State.DIALING);
-        boolean showingQuickResponseDialog = (mInCallScreen != null) &&
-                mInCallScreen.isQuickResponseDialogShowing();
         boolean showingDisconnectedConnection =
                 PhoneUtils.hasDisconnectedConnections(phone) && isShowingCallScreen;
-        boolean keepScreenOn = isRinging || isDialing ||
-                (showingDisconnectedConnection && !showingQuickResponseDialog);
+        boolean keepScreenOn = isRinging || isDialing || showingDisconnectedConnection;
         if (DBG) Log.d(LOG_TAG, "updateWakeState: keepScreenOn = " + keepScreenOn
                        + " (isRinging " + isRinging
                        + ", isDialing " + isDialing
-                       + ", showingQuickResponse " + showingQuickResponseDialog
                        + ", showingDisc " + showingDisconnectedConnection + ")");
         // keepScreenOn == true means we'll hold a full wake lock:
         requestWakeState(keepScreenOn ? WakeState.FULL : WakeState.SLEEP);
diff --git a/src/com/android/phone/RejectWithTextMessageManager.java b/src/com/android/phone/RejectWithTextMessageManager.java
index b03211a..fda8f78 100644
--- a/src/com/android/phone/RejectWithTextMessageManager.java
+++ b/src/com/android/phone/RejectWithTextMessageManager.java
@@ -73,7 +73,11 @@
     /** SharedPreferences file name for our persistent settings. */
     private static final String SHARED_PREFERENCES_NAME = "respond_via_sms_prefs";
 
-    // Preference keys for the 4 "canned responses"; see RespondViaSmsManager$Settings.
+    private Intent mIntent;
+
+    private ArrayList<ComponentName> mComponentsWithPermission = new ArrayList<ComponentName>();
+
+            // Preference keys for the 4 "canned responses"; see RespondViaSmsManager$Settings.
     // Since (for now at least) the number of messages is fixed at 4, and since
     // SharedPreferences can't deal with arrays anyway, just store the messages
     // as 4 separate strings.
@@ -82,20 +86,11 @@
     private static final String KEY_CANNED_RESPONSE_PREF_2 = "canned_response_pref_2";
     private static final String KEY_CANNED_RESPONSE_PREF_3 = "canned_response_pref_3";
     private static final String KEY_CANNED_RESPONSE_PREF_4 = "canned_response_pref_4";
-    private static final String KEY_PREFERRED_PACKAGE = "preferred_package_pref";
-    private static final String KEY_INSTANT_TEXT_DEFAULT_COMPONENT = "instant_text_def_component";
+    /* package */ static final String KEY_INSTANT_TEXT_DEFAULT_COMPONENT =
+            "instant_text_def_component";
 
-    /**
-     * Brings up the standard SMS compose UI.
-     */
-    private void launchSmsCompose(String phoneNumber) {
-        if (DBG) log("launchSmsCompose: number " + phoneNumber);
-
-        final Intent intent = getInstantTextIntent(phoneNumber, null, getSmsService());
-
-        if (DBG) log("- Launching SMS compose UI: " + intent);
-        PhoneGlobals.getInstance().startService(intent);
-    }
+    /* package */ static final String TAG_ALL_SMS_SERVICES = "com.android.phone.AvailablePackages";
+    /* package */ static final String TAG_SEND_SMS = "com.android.phone.MessageIntent";
 
     /**
      * Read the (customizable) canned responses from SharedPreferences,
@@ -130,28 +125,10 @@
         return responses;
     }
 
-    /**
-     * Sends a text message without any interaction from the user.
-     */
-    private void sendText(String phoneNumber, String message, ComponentName component) {
-        if (DBG) log("sendText: number "
-                      + phoneNumber + ", message '" + message + "'");
-
-        PhoneGlobals.getInstance().startService(getInstantTextIntent(phoneNumber, message,
-                component));
-    }
-
-    private void sendTextAndExit(String phoneNumber, String message, ComponentName component,
-            boolean setDefaultComponent) {
+    private void sendTextAndExit() {
         // Send the selected message immediately with no user interaction.
-        sendText(phoneNumber, message, component);
-
-        if (setDefaultComponent) {
-            final SharedPreferences prefs = PhoneGlobals.getInstance().getSharedPreferences(
-                    SHARED_PREFERENCES_NAME, Context.MODE_PRIVATE);
-            prefs.edit()
-                    .putString(KEY_INSTANT_TEXT_DEFAULT_COMPONENT, component.flattenToString())
-                    .apply();
+        if (mIntent.getComponent() != null) {
+            PhoneGlobals.getInstance().startService(mIntent);
         }
 
         // ...and show a brief confirmation to the user (since
@@ -231,11 +208,7 @@
         return intent;
     }
 
-    public void rejectCallWithNewMessage(String number) {
-        launchSmsCompose(number);
-    }
-
-    private ComponentName getSmsService() {
+    private boolean getSmsService() {
         if (DBG) log("sendTextToDefaultActivity()...");
         final PackageManager packageManager = PhoneGlobals.getInstance().getPackageManager();
 
@@ -257,7 +230,8 @@
 
             if (serviceInfo != null &&
                     PERMISSION_SEND_RESPOND_VIA_MESSAGE.equals(serviceInfo.permission)) {
-                return componentName;
+                mIntent.setComponent(componentName);
+                return true;
             } else {
                 SharedPreferences.Editor editor = prefs.edit();
                 editor.remove(KEY_INSTANT_TEXT_DEFAULT_COMPONENT);
@@ -265,29 +239,38 @@
             }
         }
 
-        final ArrayList<ComponentName> componentsWithPermission =
-            getPackagesWithInstantTextPermission();
+        mComponentsWithPermission = getPackagesWithInstantTextPermission();
 
-        final int size = componentsWithPermission.size();
+        final int size = mComponentsWithPermission.size();
         if (size == 0) {
             Log.e(TAG, "No appropriate package receiving the Intent. Don't send anything");
-            return null;
+            return false;
         } else if (size == 1) {
-            return componentsWithPermission.get(0);
+            mIntent.setComponent(mComponentsWithPermission.get(0));
+            return true;
         } else {
             Log.v(TAG, "Choosing from one of the apps");
             // TODO(klp): Add an app picker.
-            return componentsWithPermission.get(0);
+            final Intent intent = new Intent(Intent.ACTION_VIEW, null);
+            intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK |
+                    Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS |
+                    Intent.FLAG_ACTIVITY_NO_ANIMATION  |
+                    Intent.FLAG_ACTIVITY_NO_HISTORY |
+                    Intent.FLAG_FROM_BACKGROUND);
+            intent.setClass(PhoneGlobals.getInstance(), TextMessagePackageChooser.class);
+            intent.putExtra(TAG_ALL_SMS_SERVICES, mComponentsWithPermission);
+            intent.putExtra(TAG_SEND_SMS, mIntent);
+            PhoneGlobals.getInstance().startActivity(intent);
+            return false;
+            // return componentsWithPermission.get(0);
         }
     }
 
-
-    public void rejectCallWithMessage(final String number, String message) {
-        final ComponentName componentName = getSmsService();
-
-        if (componentName != null) {
-            sendTextAndExit(number, message, componentName,
-                    false);
+    public void rejectCallWithMessage(Call call, String message) {
+        mComponentsWithPermission.clear();
+        mIntent = getInstantTextIntent(call.getLatestConnection().getAddress(), message, null);
+        if (getSmsService())  {
+            sendTextAndExit();
         }
     }
 
diff --git a/src/com/android/phone/TextMessagePackageChooser.java b/src/com/android/phone/TextMessagePackageChooser.java
new file mode 100644
index 0000000..ae638cb
--- /dev/null
+++ b/src/com/android/phone/TextMessagePackageChooser.java
@@ -0,0 +1,218 @@
+/*
+
+ * Copyright (C) 2013 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.phone;
+
+import android.app.Activity;
+import android.app.ActivityManager;
+import android.app.AlertDialog;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.DialogInterface;
+import android.content.Intent;
+import android.content.SharedPreferences;
+import android.content.pm.ApplicationInfo;
+import android.content.pm.PackageManager;
+import android.graphics.drawable.Drawable;
+import android.os.Bundle;
+import android.util.Log;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.BaseAdapter;
+import android.widget.CheckBox;
+import android.widget.CompoundButton;
+import android.widget.ImageView;
+import android.widget.TextView;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class TextMessagePackageChooser extends Activity {
+    private static final String TAG = TextMessagePackageChooser.class.getSimpleName();
+
+    /** SharedPreferences file name for our persistent settings. */
+    private static final String SHARED_PREFERENCES_NAME = "respond_via_sms_prefs";
+
+    private int mIconSize = -1;
+
+    @Override
+    public void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        final ArrayList<ComponentName> components = getIntent().getParcelableArrayListExtra(
+                RejectWithTextMessageManager.TAG_ALL_SMS_SERVICES);
+        BaseAdapter adapter = new PackageSelectionAdapter(this, components);
+
+        PackageClickListener clickListener = new PackageClickListener(components);
+
+        final CharSequence title = getResources().getText(
+                com.android.internal.R.string.whichApplication);
+        LayoutInflater inflater =
+                (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE);
+
+        final View view = inflater.inflate(com.android.internal.R.layout.always_use_checkbox,
+                null);
+        final CheckBox alwaysUse = (CheckBox) view.findViewById(
+                com.android.internal.R.id.alwaysUse);
+        alwaysUse.setText(com.android.internal.R.string.alwaysUse);
+        alwaysUse.setOnCheckedChangeListener(clickListener);
+
+        AlertDialog.Builder builder = new AlertDialog.Builder(this)
+                .setTitle(title)
+                .setCancelable(true)
+                .setOnCancelListener(new RespondViaSmsCancelListener())
+                .setAdapter(adapter, clickListener)
+                .setView(view);
+                       
+        builder.create().show();
+    }
+    
+    private class PackageSelectionAdapter extends BaseAdapter {
+        private final LayoutInflater mInflater;
+        private final List<ComponentName> mComponents;
+
+        public PackageSelectionAdapter(Context context, List<ComponentName> components) {
+            mInflater = (LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
+            mComponents = components;
+        }
+
+        @Override
+        public int getCount() {
+            return mComponents.size();
+        }
+
+        @Override
+        public Object getItem(int position) {
+            return mComponents.get(position);
+        }
+
+        @Override
+        public long getItemId(int position) {
+            return position;
+        }
+
+        @Override
+        public View getView(int position, View convertView, ViewGroup parent) {
+            if (convertView == null) {
+                convertView = mInflater.inflate(
+                        com.android.internal.R.layout.activity_chooser_view_list_item, parent,
+                        false);
+            }
+
+            final ComponentName component = mComponents.get(position);
+            final String packageName = component.getPackageName();
+            final PackageManager packageManager = getPackageManager();
+
+            // Set the application label
+            final TextView text = (TextView) convertView.findViewById(
+                    com.android.internal.R.id.title);
+
+            text.setText("");
+            try {
+                final ApplicationInfo appInfo = packageManager.getApplicationInfo(packageName, 0);
+                final CharSequence label = packageManager.getApplicationLabel(appInfo);
+                if (label != null) {
+                    text.setText(label);
+                }
+            } catch (PackageManager.NameNotFoundException e) {
+                Log.w(TAG, "Failed to load app label because package was not found.");
+            }
+
+            // Set the application icon
+            final ImageView icon = (ImageView) convertView.findViewById(android.R.id.icon);
+            Drawable drawable = null;
+            try {
+                drawable = getPackageManager().getApplicationIcon(packageName);
+            } catch (PackageManager.NameNotFoundException e) {
+                Log.w(TAG, "Failed to load icon because it wasn't found.");
+            }
+            if (drawable == null) {
+                drawable = getPackageManager().getDefaultActivityIcon();
+            }
+            icon.setImageDrawable(drawable);
+            ViewGroup.LayoutParams lp = (ViewGroup.LayoutParams) icon.getLayoutParams();
+            lp.width = lp.height = getIconSize();
+
+            return convertView;
+        }
+
+    }
+
+    private class PackageClickListener implements DialogInterface.OnClickListener,
+            CompoundButton.OnCheckedChangeListener {
+        final private List<ComponentName> mComponents;
+        private boolean mMakeDefault = false;
+
+        public PackageClickListener(List<ComponentName> components) {
+            mComponents = components;
+        }
+
+        @Override
+        public void onClick(DialogInterface dialog, int which) {
+            final ComponentName component = mComponents.get(which);
+
+            if (mMakeDefault) {
+                final SharedPreferences prefs = PhoneGlobals.getInstance().getSharedPreferences(
+                        SHARED_PREFERENCES_NAME, Context.MODE_PRIVATE);
+                prefs.edit().putString(
+                        RejectWithTextMessageManager.KEY_INSTANT_TEXT_DEFAULT_COMPONENT,
+                        component.flattenToString()).apply();
+            }
+
+            final Intent messageIntent = (Intent) getIntent().getParcelableExtra(
+                    RejectWithTextMessageManager.TAG_SEND_SMS);
+            if (messageIntent != null) {
+                messageIntent.setComponent(component);
+                PhoneGlobals.getInstance().startService(messageIntent);
+            }
+            finish();
+        }
+
+        @Override
+        public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
+            Log.i(TAG, "mMakeDefault : " + isChecked);
+            mMakeDefault = isChecked;
+        }
+    }
+
+    /**
+     * OnCancelListener for the "Respond via SMS" popup.
+     */
+    public class RespondViaSmsCancelListener implements DialogInterface.OnCancelListener {
+        public RespondViaSmsCancelListener() {
+        }
+
+        /**
+         * Handles the user canceling the popup, either by touching
+         * outside the popup or by pressing Back.
+         */
+        @Override
+        public void onCancel(DialogInterface dialog) {
+            finish();
+        }
+    }
+
+    private int getIconSize() {
+      if (mIconSize < 0) {
+          final ActivityManager am =
+              (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE);
+          mIconSize = am.getLauncherLargeIconSize();
+      }
+
+      return mIconSize;
+    }
+}