Merge "Adopt O shortcut changes for Intent.ACTION_CREATE_SHORTCUT" into ub-contactsdialer-i-dev
diff --git a/AndroidManifest.xml b/AndroidManifest.xml
index 5035159..d44ae6e 100644
--- a/AndroidManifest.xml
+++ b/AndroidManifest.xml
@@ -185,6 +185,8 @@
             android:uiOptions="splitActionBarWhenNarrow"
             android:windowSoftInputMode="adjustResize"
             android:visibleToInstantApps="true">
+            <meta-data android:name="android.app.shortcuts.new_config"
+                android:value="true" />
             <intent-filter>
                 <action android:name="android.intent.action.INSERT_OR_EDIT"/>
                 <category android:name="android.intent.category.DEFAULT"/>
diff --git a/src/com/android/contacts/DynamicShortcuts.java b/src/com/android/contacts/DynamicShortcuts.java
index 0901e56..087b421 100644
--- a/src/com/android/contacts/DynamicShortcuts.java
+++ b/src/com/android/contacts/DynamicShortcuts.java
@@ -275,26 +275,47 @@
                 .setDisabledMessage(mContext.getString(R.string.dynamic_shortcut_disabled_message))
                 .setExtras(extras);
 
-        if (displayName.length() < mLongLabelMaxLength) {
-            builder.setLongLabel(displayName);
-        } else {
-            builder.setLongLabel(displayName.substring(0, mLongLabelMaxLength - 1).trim() + "…");
-        }
-
-        if (displayName.length() < mShortLabelMaxLength) {
-            builder.setShortLabel(displayName);
-        } else {
-            builder.setShortLabel(displayName.substring(0, mShortLabelMaxLength - 1).trim() + "…");
-        }
+        setLabel(builder, displayName);
         return builder;
     }
 
+    @VisibleForTesting
+    ShortcutInfo getActionShortcutInfo(String id, String label, Intent action, Icon icon) {
+        if (id == null || label == null) {
+            return null;
+        }
+        final PersistableBundle extras = new PersistableBundle();
+        extras.putInt(EXTRA_SHORTCUT_TYPE, SHORTCUT_TYPE_CONTACT_URI);
+
+        final ShortcutInfo.Builder builder = new ShortcutInfo.Builder(mContext, id)
+                .setIntent(action)
+                .setIcon(icon)
+                .setDisabledMessage(mContext.getString(R.string.dynamic_shortcut_disabled_message));
+
+        setLabel(builder, label);
+        return builder.build();
+    }
+
     public ShortcutInfo getQuickContactShortcutInfo(long id, String lookupKey, String displayName) {
         final ShortcutInfo.Builder builder = builderForContactShortcut(id, lookupKey, displayName);
         addIconForContact(id, lookupKey, displayName, builder);
         return builder.build();
     }
 
+    private void setLabel(ShortcutInfo.Builder builder, String label) {
+        if (label.length() < mLongLabelMaxLength) {
+            builder.setLongLabel(label);
+        } else {
+            builder.setLongLabel(label.substring(0, mLongLabelMaxLength - 1).trim() + "…");
+        }
+
+        if (label.length() < mShortLabelMaxLength) {
+            builder.setShortLabel(label);
+        } else {
+            builder.setShortLabel(label.substring(0, mShortLabelMaxLength - 1).trim() + "…");
+        }
+    }
+
     private void addIconForContact(Cursor cursor, ShortcutInfo.Builder builder) {
         final long id = cursor.getLong(0);
         final String lookupKey = cursor.getString(1);
diff --git a/src/com/android/contacts/list/ShortcutIntentBuilder.java b/src/com/android/contacts/ShortcutIntentBuilder.java
similarity index 78%
rename from src/com/android/contacts/list/ShortcutIntentBuilder.java
rename to src/com/android/contacts/ShortcutIntentBuilder.java
index 235e9f7..1019992 100644
--- a/src/com/android/contacts/list/ShortcutIntentBuilder.java
+++ b/src/com/android/contacts/ShortcutIntentBuilder.java
@@ -13,12 +13,14 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package com.android.contacts.list;
+package com.android.contacts;
 
 import android.app.ActivityManager;
 import android.content.ContentResolver;
 import android.content.Context;
 import android.content.Intent;
+import android.content.pm.ShortcutInfo;
+import android.content.pm.ShortcutManager;
 import android.content.res.Resources;
 import android.database.Cursor;
 import android.graphics.Bitmap;
@@ -29,6 +31,7 @@
 import android.graphics.Rect;
 import android.graphics.drawable.BitmapDrawable;
 import android.graphics.drawable.Drawable;
+import android.graphics.drawable.Icon;
 import android.net.Uri;
 import android.os.AsyncTask;
 import android.provider.ContactsContract.CommonDataKinds.Phone;
@@ -37,18 +40,20 @@
 import android.provider.ContactsContract.Data;
 import android.support.v4.graphics.drawable.RoundedBitmapDrawable;
 import android.support.v4.graphics.drawable.RoundedBitmapDrawableFactory;
+import android.support.v4.os.BuildCompat;
 import android.telecom.PhoneAccount;
 import android.text.TextPaint;
 import android.text.TextUtils;
 import android.text.TextUtils.TruncateAt;
 
-import com.android.contacts.ContactPhotoManager;
 import com.android.contacts.ContactPhotoManager.DefaultImageRequest;
-import com.android.contacts.ContactsUtils;
-import com.android.contacts.R;
 import com.android.contacts.util.BitmapUtil;
 import com.android.contacts.util.ImplicitIntentsUtil;
 
+import com.google.common.collect.Lists;
+
+import java.util.List;
+
 /**
  * Constructs shortcut intents.
  */
@@ -264,22 +269,30 @@
 
     private void createContactShortcutIntent(Uri contactUri, String contentType, String displayName,
             String lookupKey, byte[] bitmapData) {
-        Drawable drawable = getPhotoDrawable(bitmapData, displayName, lookupKey);
+        final Drawable drawable = getPhotoDrawable(bitmapData, displayName, lookupKey);
+        if (TextUtils.isEmpty(displayName)) {
+            displayName = mContext.getResources().getString(R.string.missing_name);
+        }
 
         final Intent shortcutIntent = ImplicitIntentsUtil.getIntentForQuickContactLauncherShortcut(
                 mContext, contactUri);
 
         final Bitmap icon = generateQuickContactIcon(drawable);
 
-        Intent intent = new Intent();
+        Intent intent = null;
+        if (BuildCompat.isAtLeastO()) {
+            final ShortcutManager sm = (ShortcutManager)
+                    mContext.getSystemService(Context.SHORTCUT_SERVICE);
+            final DynamicShortcuts dynamicShortcuts = new DynamicShortcuts(mContext);
+            final ShortcutInfo shortcutInfo = dynamicShortcuts.getActionShortcutInfo(
+                    lookupKey, displayName, shortcutIntent, Icon.createWithBitmap(icon));
+            intent = sm.createShortcutResultIntent(shortcutInfo);
+        }
+
+        intent = intent == null ? new Intent() : intent;
         intent.putExtra(Intent.EXTRA_SHORTCUT_ICON, icon);
         intent.putExtra(Intent.EXTRA_SHORTCUT_INTENT, shortcutIntent);
-        if (TextUtils.isEmpty(displayName)) {
-            intent.putExtra(Intent.EXTRA_SHORTCUT_NAME, mContext.getResources().getString(
-                    R.string.missing_name));
-        } else {
-            intent.putExtra(Intent.EXTRA_SHORTCUT_NAME, displayName);
-        }
+        intent.putExtra(Intent.EXTRA_SHORTCUT_NAME, displayName);
 
         mListener.onShortcutIntentCreated(contactUri, intent);
     }
@@ -287,31 +300,42 @@
     private void createPhoneNumberShortcutIntent(Uri uri, String displayName, String lookupKey,
             byte[] bitmapData, String phoneNumber, int phoneType, String phoneLabel,
             String shortcutAction) {
-        Drawable drawable = getPhotoDrawable(bitmapData, displayName, lookupKey);
-
-        Bitmap bitmap;
-        Uri phoneUri;
-        if (Intent.ACTION_CALL.equals(shortcutAction)) {
-            // Make the URI a direct tel: URI so that it will always continue to work
-            phoneUri = Uri.fromParts(PhoneAccount.SCHEME_TEL, phoneNumber, null);
-            bitmap = generatePhoneNumberIcon(drawable, phoneType, phoneLabel,
-                    R.drawable.quantum_ic_phone_vd_theme_24);
-        } else {
-            phoneUri = Uri.fromParts(ContactsUtils.SCHEME_SMSTO, phoneNumber, null);
-            bitmap = generatePhoneNumberIcon(drawable, phoneType, phoneLabel,
-                    R.drawable.quantum_ic_message_vd_theme_24);
-        }
-
-        Intent shortcutIntent = new Intent(shortcutAction, phoneUri);
-        shortcutIntent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
-
-        Intent intent = new Intent();
-        intent.putExtra(Intent.EXTRA_SHORTCUT_ICON, bitmap);
-        intent.putExtra(Intent.EXTRA_SHORTCUT_INTENT, shortcutIntent);
+        final Drawable drawable = getPhotoDrawable(bitmapData, displayName, lookupKey);
+        final Bitmap icon;
+        final Uri phoneUri;
 
         if (TextUtils.isEmpty(displayName)) {
             displayName = mContext.getResources().getString(R.string.missing_name);
         }
+
+        if (Intent.ACTION_CALL.equals(shortcutAction)) {
+            // Make the URI a direct tel: URI so that it will always continue to work
+            phoneUri = Uri.fromParts(PhoneAccount.SCHEME_TEL, phoneNumber, null);
+            icon = generatePhoneNumberIcon(drawable, phoneType, phoneLabel,
+                    R.drawable.quantum_ic_phone_vd_theme_24);
+        } else {
+            phoneUri = Uri.fromParts(ContactsUtils.SCHEME_SMSTO, phoneNumber, null);
+            icon = generatePhoneNumberIcon(drawable, phoneType, phoneLabel,
+                    R.drawable.quantum_ic_message_vd_theme_24);
+        }
+
+        final Intent shortcutIntent = new Intent(shortcutAction, phoneUri);
+        shortcutIntent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
+
+        Intent intent = null;
+        if (BuildCompat.isAtLeastO()) {
+            final ShortcutManager sm = (ShortcutManager)
+                    mContext.getSystemService(Context.SHORTCUT_SERVICE);
+            final String id = shortcutAction + lookupKey;
+            final DynamicShortcuts dynamicShortcuts = new DynamicShortcuts(mContext);
+            final ShortcutInfo shortcutInfo = dynamicShortcuts.getActionShortcutInfo(
+                    id, displayName, shortcutIntent, Icon.createWithBitmap(icon));
+            intent = sm.createShortcutResultIntent(shortcutInfo);
+        }
+
+        intent = intent == null ? new Intent() : intent;
+        intent.putExtra(Intent.EXTRA_SHORTCUT_ICON, icon);
+        intent.putExtra(Intent.EXTRA_SHORTCUT_INTENT, shortcutIntent);
         if (TextUtils.equals(shortcutAction, Intent.ACTION_CALL)) {
             intent.putExtra(Intent.EXTRA_SHORTCUT_NAME,
                     mContext.getResources().getString(R.string.call_by_shortcut, displayName));
@@ -371,31 +395,36 @@
         photoPaint.setFilterBitmap(true);
         Rect dst = new Rect(0, 0, mIconSize, mIconSize);
 
-        // Create an overlay for the phone number type
-        CharSequence overlay = Phone.getTypeLabel(r, phoneType, phoneLabel);
+        // Create the overlay if we're pre-O. O created shortcuts have the app badge which overlaps
+        // the type overlay.
+        if (!BuildCompat.isAtLeastO()) {
+            // Create an overlay for the phone number type
+            CharSequence overlay = Phone.getTypeLabel(r, phoneType, phoneLabel);
 
-        if (overlay != null) {
-            TextPaint textPaint = new TextPaint(Paint.ANTI_ALIAS_FLAG | Paint.DEV_KERN_TEXT_FLAG);
-            textPaint.setTextSize(r.getDimension(R.dimen.shortcut_overlay_text_size));
-            textPaint.setColor(r.getColor(R.color.textColorIconOverlay));
-            textPaint.setShadowLayer(4f, 0, 2f, r.getColor(R.color.textColorIconOverlayShadow));
+            if (overlay != null) {
+                TextPaint textPaint = new TextPaint(
+                        Paint.ANTI_ALIAS_FLAG | Paint.DEV_KERN_TEXT_FLAG);
+                textPaint.setTextSize(r.getDimension(R.dimen.shortcut_overlay_text_size));
+                textPaint.setColor(r.getColor(R.color.textColorIconOverlay));
+                textPaint.setShadowLayer(4f, 0, 2f, r.getColor(R.color.textColorIconOverlayShadow));
 
-            final FontMetricsInt fmi = textPaint.getFontMetricsInt();
+                final FontMetricsInt fmi = textPaint.getFontMetricsInt();
 
-            // First fill in a darker background around the text to be drawn
-            final Paint workPaint = new Paint();
-            workPaint.setColor(mOverlayTextBackgroundColor);
-            workPaint.setStyle(Paint.Style.FILL);
-            final int textPadding = r
-                    .getDimensionPixelOffset(R.dimen.shortcut_overlay_text_background_padding);
-            final int textBandHeight = (fmi.descent - fmi.ascent) + textPadding * 2;
-            dst.set(0, mIconSize - textBandHeight, mIconSize, mIconSize);
-            canvas.drawRect(dst, workPaint);
+                // First fill in a darker background around the text to be drawn
+                final Paint workPaint = new Paint();
+                workPaint.setColor(mOverlayTextBackgroundColor);
+                workPaint.setStyle(Paint.Style.FILL);
+                final int textPadding = r
+                        .getDimensionPixelOffset(R.dimen.shortcut_overlay_text_background_padding);
+                final int textBandHeight = (fmi.descent - fmi.ascent) + textPadding * 2;
+                dst.set(0, mIconSize - textBandHeight, mIconSize, mIconSize);
+                canvas.drawRect(dst, workPaint);
 
-            overlay = TextUtils.ellipsize(overlay, textPaint, mIconSize, TruncateAt.END);
-            final float textWidth = textPaint.measureText(overlay, 0, overlay.length());
-            canvas.drawText(overlay, 0, overlay.length(), (mIconSize - textWidth) / 2, mIconSize
-                    - fmi.descent - textPadding, textPaint);
+                overlay = TextUtils.ellipsize(overlay, textPaint, mIconSize, TruncateAt.END);
+                final float textWidth = textPaint.measureText(overlay, 0, overlay.length());
+                canvas.drawText(overlay, 0, overlay.length(), (mIconSize - textWidth) / 2, mIconSize
+                        - fmi.descent - textPadding, textPaint);
+            }
         }
 
         // Draw the phone action icon as an overlay
diff --git a/src/com/android/contacts/list/ContactPickerFragment.java b/src/com/android/contacts/list/ContactPickerFragment.java
index e1f33b4..504828f 100644
--- a/src/com/android/contacts/list/ContactPickerFragment.java
+++ b/src/com/android/contacts/list/ContactPickerFragment.java
@@ -24,7 +24,8 @@
 import android.widget.AdapterView;
 
 import com.android.contacts.R;
-import com.android.contacts.list.ShortcutIntentBuilder.OnShortcutIntentCreatedListener;
+import com.android.contacts.ShortcutIntentBuilder;
+import com.android.contacts.ShortcutIntentBuilder.OnShortcutIntentCreatedListener;
 
 /**
  * Fragment for the contact list used for browsing contacts (as compared to
diff --git a/src/com/android/contacts/list/PhoneNumberPickerFragment.java b/src/com/android/contacts/list/PhoneNumberPickerFragment.java
index 6a736db..ab78e0d 100644
--- a/src/com/android/contacts/list/PhoneNumberPickerFragment.java
+++ b/src/com/android/contacts/list/PhoneNumberPickerFragment.java
@@ -28,7 +28,8 @@
 import android.view.ViewGroup;
 
 import com.android.contacts.R;
-import com.android.contacts.list.ShortcutIntentBuilder.OnShortcutIntentCreatedListener;
+import com.android.contacts.ShortcutIntentBuilder;
+import com.android.contacts.ShortcutIntentBuilder.OnShortcutIntentCreatedListener;
 
 /**
  * Fragment containing a phone number list for picking.
diff --git a/src/com/android/contacts/quickcontact/QuickContactActivity.java b/src/com/android/contacts/quickcontact/QuickContactActivity.java
index e0986d5..014e1d5 100644
--- a/src/com/android/contacts/quickcontact/QuickContactActivity.java
+++ b/src/com/android/contacts/quickcontact/QuickContactActivity.java
@@ -126,8 +126,8 @@
 import com.android.contacts.interactions.SmsInteractionsLoader;
 import com.android.contacts.interactions.TouchPointManager;
 import com.android.contacts.lettertiles.LetterTileDrawable;
-import com.android.contacts.list.ShortcutIntentBuilder;
-import com.android.contacts.list.ShortcutIntentBuilder.OnShortcutIntentCreatedListener;
+import com.android.contacts.ShortcutIntentBuilder;
+import com.android.contacts.ShortcutIntentBuilder.OnShortcutIntentCreatedListener;
 import com.android.contacts.list.UiIntentActions;
 import com.android.contacts.logging.Logger;
 import com.android.contacts.logging.QuickContactEvent.ActionType;
diff --git a/src/com/android/contacts/util/ImplicitIntentsUtil.java b/src/com/android/contacts/util/ImplicitIntentsUtil.java
index 7465c96..0d00519 100644
--- a/src/com/android/contacts/util/ImplicitIntentsUtil.java
+++ b/src/com/android/contacts/util/ImplicitIntentsUtil.java
@@ -16,7 +16,7 @@
 
 package com.android.contacts.util;
 
-import static com.android.contacts.list.ShortcutIntentBuilder.INTENT_EXTRA_IGNORE_LAUNCH_ANIMATION;
+import static com.android.contacts.ShortcutIntentBuilder.INTENT_EXTRA_IGNORE_LAUNCH_ANIMATION;
 
 import android.app.Activity;
 import android.content.Context;