am 333a615d: Implement call and SMS shortcuts.

Merge commit '333a615d1e6ced4560f4803510e673bae87d0ca2'

* commit '333a615d1e6ced4560f4803510e673bae87d0ca2':
  Implement call and SMS shortcuts.
diff --git a/AndroidManifest.xml b/AndroidManifest.xml
index e4fd510..fb734c4 100644
--- a/AndroidManifest.xml
+++ b/AndroidManifest.xml
@@ -246,6 +246,30 @@
 
         </activity-alias>
 
+        <activity-alias android:name="alias.DialShortcut"
+            android:targetActivity="ContactsListActivity"
+            android:label="@string/shortcutDialContact"
+            android:icon="@drawable/ic_launcher_shortcut_contact">
+
+            <intent-filter>
+                <action android:name="android.intent.action.CREATE_SHORTCUT" />
+                <category android:name="android.intent.category.DEFAULT" />
+            </intent-filter>
+
+        </activity-alias>
+
+        <activity-alias android:name="alias.MessageShortcut"
+            android:targetActivity="ContactsListActivity"
+            android:label="@string/shortcutMessageContact"
+            android:icon="@drawable/ic_launcher_shortcut_contact">
+
+            <intent-filter>
+                <action android:name="android.intent.action.CREATE_SHORTCUT" />
+                <category android:name="android.intent.category.DEFAULT" />
+            </intent-filter>
+
+        </activity-alias>
+
         <activity android:name="CallDetailActivity"
             android:label="@string/callDetailTitle"
             android:theme="@style/TallTitleBarTheme"
diff --git a/res/drawable-finger/badge_action_call.png b/res/drawable-finger/badge_action_call.png
new file mode 100644
index 0000000..3bc88a3
--- /dev/null
+++ b/res/drawable-finger/badge_action_call.png
Binary files differ
diff --git a/res/drawable-finger/badge_action_sms.png b/res/drawable-finger/badge_action_sms.png
new file mode 100644
index 0000000..bbcfb59
--- /dev/null
+++ b/res/drawable-finger/badge_action_sms.png
Binary files differ
diff --git a/res/values/colors.xml b/res/values/colors.xml
new file mode 100644
index 0000000..fb4019d
--- /dev/null
+++ b/res/values/colors.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2009 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.
+-->
+
+<resources>
+    <color name="textColorIconOverlay">#fff</color>
+    <color name="textColorIconOverlayShadow">#000</color>
+</resources>
diff --git a/res/values/strings.xml b/res/values/strings.xml
index 4442086..6eff5b4 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -27,6 +27,23 @@
          This shows up in a list of things like bookmark, folder, music playlist, etc -->
     <string name="shortcutContact">Contact</string>
 
+    <!-- Name of activity that allows users to create shortcuts on the home screen to dial a contact.
+         This shows up in a list of things like bookmark, folder, music playlist, etc -->
+    <string name="shortcutDialContact">Direct Dial</string>
+
+    <!-- Name of activity that allows users to create shortcuts on the home screen to message (SMS) a contact.
+         This shows up in a list of things like bookmark, folder, music playlist, etc -->
+    <string name="shortcutMessageContact">Direct Message</string>
+
+    <!-- Activity title when the user is selecting a contact for a shortcut. -->
+    <string name="shortcutActivityTitle">Choose a contact shortcut</string>
+    
+    <!-- Activity title when the user is selecting a contact for a direct dial shortcut. -->
+    <string name="callShortcutActivityTitle">Choose a number to call</string>
+    
+    <!-- Activity title when the user is selecting a contact for a direct message shortcut. -->
+    <string name="messageShortcutActivityTitle">Choose a number to message</string>
+        
     <!-- Title for the activity that shows only starred contacts -->
     <string name="starredList">Starred</string>
 
diff --git a/src/com/android/contacts/ContactsListActivity.java b/src/com/android/contacts/ContactsListActivity.java
index d97c27d..e5143e0 100644
--- a/src/com/android/contacts/ContactsListActivity.java
+++ b/src/com/android/contacts/ContactsListActivity.java
@@ -30,10 +30,17 @@
 import android.content.ISyncAdapter;
 import android.content.Intent;
 import android.content.SharedPreferences;
+import android.content.res.Resources;
 import android.database.CharArrayBuffer;
 import android.database.Cursor;
 import android.graphics.Bitmap;
 import android.graphics.BitmapFactory;
+import android.graphics.Canvas;
+import android.graphics.Paint;
+import android.graphics.Rect;
+import android.graphics.Typeface;
+import android.graphics.drawable.BitmapDrawable;
+import android.graphics.drawable.Drawable;
 import android.net.Uri;
 import android.os.Bundle;
 import android.os.Handler;
@@ -83,6 +90,8 @@
         implements View.OnCreateContextMenuListener, DialogInterface.OnClickListener {
     private static final String TAG = "ContactsListActivity";
 
+    private static final boolean ENABLE_ACTION_ICON_OVERLAYS = false;
+
     private static final String LIST_STATE_KEY = "liststate";
     private static final String FOCUS_KEY = "focused";
     
@@ -291,7 +300,7 @@
     private Parcelable mListState = null;
     private boolean mListHasFocus;
 
-    private boolean mCreateShortcut;
+    private String mShortcutAction;
     private boolean mDefaultMode = false;
     
     /**
@@ -401,8 +410,19 @@
                 mMode = MODE_PICK_POSTAL;
             }
         } else if (Intent.ACTION_CREATE_SHORTCUT.equals(action)) {
-            mMode = MODE_PICK_OR_CREATE_CONTACT;
-            mCreateShortcut = true;
+            if (intent.getComponent().getClassName().equals("alias.DialShortcut")) {
+                mMode = MODE_PICK_PHONE;
+                mShortcutAction = Intent.ACTION_CALL;
+                setTitle(R.string.callShortcutActivityTitle);
+            } else if (intent.getComponent().getClassName().equals("alias.MessageShortcut")) {
+                mMode = MODE_PICK_PHONE;
+                mShortcutAction = Intent.ACTION_SENDTO;
+                setTitle(R.string.messageShortcutActivityTitle);
+            } else {
+                mMode = MODE_PICK_OR_CREATE_CONTACT;
+                mShortcutAction = Intent.ACTION_VIEW;
+                setTitle(R.string.shortcutActivityTitle);
+            }
         } else if (Intent.ACTION_GET_CONTENT.equals(action)) {
             final String type = intent.resolveType(this);
             if (People.CONTENT_ITEM_TYPE.equals(type)) {
@@ -881,8 +901,8 @@
             case SUBACTIVITY_NEW_CONTACT:
                 if (resultCode == RESULT_OK) {
                     // Contact was created, pass it back
-                    returnPickerResult(data.getStringExtra(Intent.EXTRA_SHORTCUT_NAME),
-                            data.getData());
+                    returnPickerResult(null, data.getStringExtra(Intent.EXTRA_SHORTCUT_NAME),
+                            data.getData(), 0);
                 }
         }
     }
@@ -1066,18 +1086,22 @@
             } else if (mMode == MODE_PICK_CONTACT 
                     || mMode == MODE_PICK_OR_CREATE_CONTACT) {
                 Uri uri = ContentUris.withAppendedId(People.CONTENT_URI, id);
-                if (mCreateShortcut) {
+                if (mShortcutAction != null) {
                     // Subtract one if we have Create Contact at the top
                     Cursor c = (Cursor) mAdapter.getItem(position
                             - (mMode == MODE_PICK_OR_CREATE_CONTACT? 1:0));
-                    returnPickerResult(c.getString(NAME_COLUMN_INDEX), uri);
+                    returnPickerResult(c, c.getString(NAME_COLUMN_INDEX), uri, id);
                 } else {
-                    returnPickerResult(null, uri);
+                    returnPickerResult(null, null, uri, id);
                 }
             } else if (mMode == MODE_PICK_PHONE) {
-                setResult(RESULT_OK, new Intent().setData(
-                        ContentUris.withAppendedId(Phones.CONTENT_URI, id)));
-                finish();
+                Uri uri = ContentUris.withAppendedId(Phones.CONTENT_URI, id);
+                if (mShortcutAction != null) {
+                    Cursor c = (Cursor) mAdapter.getItem(position);
+                    returnPickerResult(c, c.getString(NAME_COLUMN_INDEX), uri, id);
+                } else {
+                    returnPickerResult(null, null, uri, id);
+                }
             } else if (mMode == MODE_PICK_POSTAL) {
                 setResult(RESULT_OK, new Intent().setData(
                         ContentUris.withAppendedId(ContactMethods.CONTENT_URI, id)));
@@ -1092,22 +1116,47 @@
         }
     }
 
-    private void returnPickerResult(String name, Uri uri) {
+    private void returnPickerResult(Cursor c, String name, Uri uri, long id) {
         final Intent intent = new Intent();
     
-        if (mCreateShortcut) {
-            Intent shortcutIntent = new Intent(Intent.ACTION_VIEW, uri);
+        if (mShortcutAction != null) {
+            Intent shortcutIntent;
+            if (Intent.ACTION_VIEW.equals(mShortcutAction)) {
+                // This is a simple shortcut to view a contact.
+                shortcutIntent = new Intent(mShortcutAction, uri);
+                final Bitmap icon = People.loadContactPhoto(this, uri, 0, null);
+                if (icon != null) {
+                    intent.putExtra(Intent.EXTRA_SHORTCUT_ICON, icon);
+                } else {
+                    intent.putExtra(Intent.EXTRA_SHORTCUT_ICON_RESOURCE,
+                            Intent.ShortcutIconResource.fromContext(this,
+                                    R.drawable.ic_launcher_shortcut_contact));
+                }
+            } else {
+                // This is a direct dial or sms shortcut.
+                String number = c.getString(DATA_COLUMN_INDEX);
+                int type = c.getInt(TYPE_COLUMN_INDEX);
+                String scheme;
+                int resid;
+                if (Intent.ACTION_CALL.equals(mShortcutAction)) {
+                    scheme = "tel";
+                    resid = R.drawable.badge_action_call;
+                } else {
+                    scheme = "smsto";
+                    resid = R.drawable.badge_action_sms;
+                }
+                // Make the URI a direct tel: URI so that it will always continue to work
+                Uri phoneUri = Uri.fromParts(scheme, number, null);
+                shortcutIntent = new Intent(mShortcutAction, phoneUri);
+                
+                Uri personUri = ContentUris.withAppendedId(People.CONTENT_URI, id);
+                intent.putExtra(Intent.EXTRA_SHORTCUT_ICON,
+                        generatePhoneNumberIcon(personUri, type, resid));
+                
+            }
             shortcutIntent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
             intent.putExtra(Intent.EXTRA_SHORTCUT_INTENT, shortcutIntent);
             intent.putExtra(Intent.EXTRA_SHORTCUT_NAME, name);
-            final Bitmap icon = People.loadContactPhoto(this, uri, 0, null);
-            if (icon != null) {
-                intent.putExtra(Intent.EXTRA_SHORTCUT_ICON, icon);
-            } else {
-                intent.putExtra(Intent.EXTRA_SHORTCUT_ICON_RESOURCE,
-                        Intent.ShortcutIconResource.fromContext(this,
-                                R.drawable.ic_launcher_shortcut_contact));
-            }
             setResult(RESULT_OK, intent);
         } else {
             setResult(RESULT_OK, intent.setData(uri));
@@ -1115,6 +1164,107 @@
         finish();
     }
 
+    /**
+     * Generates a phone number shortcut icon. Adds an overlay describing the type of the phone
+     * number, and if there is a photo also adds the call action icon.
+     *
+     * @param personUri The person the phone number belongs to
+     * @param type The type of the phone number
+     * @param actionResId The ID for the action resource
+     * @return The bitmap for the icon
+     */
+    private Bitmap generatePhoneNumberIcon(Uri personUri, int type, int actionResId) {
+        final Resources r = getResources();
+        boolean drawPhoneOverlay = true;
+
+        Bitmap photo = People.loadContactPhoto(this, personUri, 0, null);
+        if (photo == null) {
+            // If there isn't a photo use the generic phone action icon instead
+            Bitmap phoneIcon = getPhoneActionIcon(r, actionResId);
+            if (phoneIcon != null) {
+                photo = phoneIcon;
+                drawPhoneOverlay = false;
+            } else {
+                return null;
+            }
+        }
+
+        // Setup the drawing classes
+        int iconSize = (int) r.getDimension(android.R.dimen.app_icon_size);
+        Bitmap icon = Bitmap.createBitmap(iconSize, iconSize, Bitmap.Config.ARGB_8888);
+        Canvas canvas = new Canvas(icon);
+
+        // Copy in the photo
+        Paint photoPaint = new Paint();
+        photoPaint.setDither(true);
+        photoPaint.setFilterBitmap(true);
+        Rect src = new Rect(0,0, photo.getWidth(),photo.getHeight());
+        Rect dst = new Rect(0,0, iconSize,iconSize);
+        canvas.drawBitmap(photo, src, dst, photoPaint);
+
+        // Create an overlay for the phone number type
+        String overlay = null;
+        switch (type) {
+            case Phones.TYPE_HOME:
+                overlay = "H";
+                break;
+
+            case Phones.TYPE_MOBILE:
+                overlay = "M";
+                break;
+
+            case Phones.TYPE_WORK:
+                overlay = "W";
+                break;
+
+            case Phones.TYPE_PAGER:
+                overlay = "P";
+                break;
+
+            case Phones.TYPE_OTHER:
+                overlay = "O";
+                break;
+        }
+        if (overlay != null) {
+            Paint textPaint = new Paint(Paint.ANTI_ALIAS_FLAG | Paint.DEV_KERN_TEXT_FLAG);
+            textPaint.setTextSize(20.0f);
+            textPaint.setTypeface(Typeface.DEFAULT_BOLD);
+            textPaint.setColor(r.getColor(R.color.textColorIconOverlay));
+            textPaint.setShadowLayer(3f, 1, 1, r.getColor(R.color.textColorIconOverlayShadow));
+            canvas.drawText(overlay, 2, 16, textPaint);
+        }
+
+        // Draw the phone action icon as an overlay
+        if (ENABLE_ACTION_ICON_OVERLAYS && drawPhoneOverlay) {
+            Bitmap phoneIcon = getPhoneActionIcon(r, actionResId);
+            if (phoneIcon != null) {
+                src.set(0,0, phoneIcon.getWidth(),phoneIcon.getHeight());
+                int iconWidth = icon.getWidth();
+                dst.set(iconWidth - 20, -1, iconWidth, 19);
+                canvas.drawBitmap(phoneIcon, src, dst, photoPaint);
+            }
+        }
+
+        return icon;
+    }
+
+    /**
+     * Returns the icon for the phone call action.
+     *
+     * @param r The resources to load the icon from
+     * @param resId The resource ID to load
+     * @return the icon for the phone call action
+     */
+    private Bitmap getPhoneActionIcon(Resources r, int resId) {
+        Drawable phoneIcon = r.getDrawable(resId);
+        if (phoneIcon instanceof BitmapDrawable) {
+            BitmapDrawable bd = (BitmapDrawable) phoneIcon;
+            return bd.getBitmap();
+        } else {
+            return null;
+        }
+    }
+    
     String[] getProjection() {
         switch (mMode) {
             case MODE_GROUP: