Report usage of dynamic shortcuts.
Test
Manual:
* verify that app doesn't crash when quick contacts activity is opened on
pre-N_MR1 device
* verify that usage is reported on N_MR1 with debugger
* Verify that shortcuts still update when a contact is favorited.
Bug 30189449
Change-Id: If2f959857dbb232482047637f8da94b610964c87
diff --git a/src/com/android/contacts/DynamicShortcuts.java b/src/com/android/contacts/DynamicShortcuts.java
index f02306c..c21f3a0 100644
--- a/src/com/android/contacts/DynamicShortcuts.java
+++ b/src/com/android/contacts/DynamicShortcuts.java
@@ -45,6 +45,7 @@
import com.android.contacts.common.ContactPhotoManager;
import com.android.contacts.common.Experiments;
+import com.android.contacts.common.compat.CompatUtils;
import com.android.contacts.common.util.BitmapUtil;
import com.android.contacts.common.util.ImplicitIntentsUtil;
import com.android.contactsbind.experiments.Flags;
@@ -68,6 +69,11 @@
public class DynamicShortcuts {
private static final String TAG = "DynamicShortcuts";
+ // Must be the same as shortcutId in res/xml/shortcuts.xml
+ // Note: This doesn't fit very well because this is a "static" shortcut but it's still the most
+ // sensible place to put it right now.
+ public static final String SHORTCUT_ADD_CONTACT = "shortcut-add-contact";
+
// Note the Nexus launcher automatically truncates shortcut labels if they exceed these limits
// however, we implement our own truncation in case the shortcut is shown on a launcher that
// has different behavior
@@ -372,7 +378,10 @@
.addTriggerContentUri(new JobInfo.TriggerContentUri(ContactsContract.AUTHORITY_URI,
JobInfo.TriggerContentUri.FLAG_NOTIFY_FOR_DESCENDANTS))
.setTriggerContentUpdateDelay(mContentChangeMinUpdateDelay)
- .setTriggerContentMaxDelay(mContentChangeMaxUpdateDelay).build();
+ .setTriggerContentMaxDelay(mContentChangeMaxUpdateDelay)
+ // Minimize impact on UX by waiting for idle before updating.
+ .setRequiresDeviceIdle(true)
+ .build();
mJobScheduler.schedule(job);
}
@@ -390,7 +399,7 @@
flags.getInteger(Experiments.DYNAMIC_MAX_CONTENT_CHANGE_UPDATE_DELAY_MILLIS));
}
- if (Build.VERSION.SDK_INT < Build.VERSION_CODES.N_MR1) return;
+ if (!CompatUtils.isLauncherShortcutCompatible()) return;
final DynamicShortcuts shortcuts = new DynamicShortcuts(context);
if (!Flags.getInstance(context).getBoolean(Experiments.DYNAMIC_SHORTCUTS)) {
@@ -426,6 +435,13 @@
return scheduler.getPendingJob(ContactsJobService.DYNAMIC_SHORTCUTS_JOB_ID) != null;
}
+ public static void reportShortcutUsed(Context context, String lookupKey) {
+ if (!CompatUtils.isLauncherShortcutCompatible()) return;
+ final ShortcutManager shortcutManager = (ShortcutManager) context
+ .getSystemService(Context.SHORTCUT_SERVICE);
+ shortcutManager.reportShortcutUsed(lookupKey);
+ }
+
private static class ShortcutUpdateTask extends AsyncTask<Void, Void, Void> {
private DynamicShortcuts mDynamicShortcuts;
diff --git a/src/com/android/contacts/activities/CompactContactEditorActivity.java b/src/com/android/contacts/activities/CompactContactEditorActivity.java
index dc16049..fa2cb23 100644
--- a/src/com/android/contacts/activities/CompactContactEditorActivity.java
+++ b/src/com/android/contacts/activities/CompactContactEditorActivity.java
@@ -16,6 +16,7 @@
package com.android.contacts.activities;
+import com.android.contacts.DynamicShortcuts;
import com.android.contacts.R;
import com.android.contacts.common.activity.RequestPermissionsActivity;
import com.android.contacts.common.model.RawContactDeltaList;
@@ -174,6 +175,10 @@
final String action = getIntent().getAction();
final Uri uri = Intent.ACTION_EDIT.equals(action) ? getIntent().getData() : null;
mFragment.load(action, uri, getIntent().getExtras());
+
+ if (Intent.ACTION_INSERT.equals(action)) {
+ DynamicShortcuts.reportShortcutUsed(this, DynamicShortcuts.SHORTCUT_ADD_CONTACT);
+ }
}
protected void onSaveInstanceState(Bundle outState) {
diff --git a/src/com/android/contacts/common/compat/CompatUtils.java b/src/com/android/contacts/common/compat/CompatUtils.java
index 567f183..a394093 100644
--- a/src/com/android/contacts/common/compat/CompatUtils.java
+++ b/src/com/android/contacts/common/compat/CompatUtils.java
@@ -173,6 +173,16 @@
return VERSION.SDK_INT >= 24;
}
+
+ public static boolean isNougatMr1Compatible() {
+ return SdkVersionOverride.getSdkVersion(Build.VERSION_CODES.N_MR1)
+ >= Build.VERSION_CODES.N_MR1;
+ }
+
+ public static boolean isLauncherShortcutCompatible() {
+ return isNougatMr1Compatible();
+ }
+
/**
* Determines if the given class is available. Can be used to check if system apis exist at
* runtime.
diff --git a/src/com/android/contacts/quickcontact/QuickContactActivity.java b/src/com/android/contacts/quickcontact/QuickContactActivity.java
index 8f67d95..4ab1953 100644
--- a/src/com/android/contacts/quickcontact/QuickContactActivity.java
+++ b/src/com/android/contacts/quickcontact/QuickContactActivity.java
@@ -64,9 +64,9 @@
import android.provider.ContactsContract.CommonDataKinds.Website;
import android.provider.ContactsContract.Contacts;
import android.provider.ContactsContract.Data;
+import android.provider.ContactsContract.DataUsageFeedback;
import android.provider.ContactsContract.Directory;
import android.provider.ContactsContract.DisplayNameSources;
-import android.provider.ContactsContract.DataUsageFeedback;
import android.provider.ContactsContract.Intents;
import android.provider.ContactsContract.QuickContact;
import android.provider.ContactsContract.RawContacts;
@@ -105,6 +105,7 @@
import com.android.contacts.ContactSaveService;
import com.android.contacts.ContactsActivity;
+import com.android.contacts.DynamicShortcuts;
import com.android.contacts.NfcHandler;
import com.android.contacts.R;
import com.android.contacts.activities.ContactEditorBaseActivity;
@@ -125,16 +126,18 @@
import com.android.contacts.common.list.ShortcutIntentBuilder;
import com.android.contacts.common.list.ShortcutIntentBuilder.OnShortcutIntentCreatedListener;
import com.android.contacts.common.logging.Logger;
-import com.android.contacts.common.logging.ScreenEvent.ScreenType;
-import com.android.contacts.common.logging.QuickContactEvent.ContactType;
-import com.android.contacts.common.logging.QuickContactEvent.CardType;
import com.android.contacts.common.logging.QuickContactEvent.ActionType;
+import com.android.contacts.common.logging.QuickContactEvent.CardType;
+import com.android.contacts.common.logging.QuickContactEvent.ContactType;
+import com.android.contacts.common.logging.ScreenEvent.ScreenType;
import com.android.contacts.common.model.AccountTypeManager;
import com.android.contacts.common.model.Contact;
import com.android.contacts.common.model.ContactLoader;
import com.android.contacts.common.model.RawContact;
+import com.android.contacts.common.model.ValuesDelta;
import com.android.contacts.common.model.account.AccountType;
import com.android.contacts.common.model.account.AccountWithDataSet;
+import com.android.contacts.common.model.dataitem.CustomDataItem;
import com.android.contacts.common.model.dataitem.DataItem;
import com.android.contacts.common.model.dataitem.DataKind;
import com.android.contacts.common.model.dataitem.EmailDataItem;
@@ -149,10 +152,8 @@
import com.android.contacts.common.model.dataitem.StructuredNameDataItem;
import com.android.contacts.common.model.dataitem.StructuredPostalDataItem;
import com.android.contacts.common.model.dataitem.WebsiteDataItem;
-import com.android.contacts.common.model.dataitem.CustomDataItem;
-import com.android.contacts.common.model.ValuesDelta;
-import com.android.contacts.common.util.ImplicitIntentsUtil;
import com.android.contacts.common.util.DateUtils;
+import com.android.contacts.common.util.ImplicitIntentsUtil;
import com.android.contacts.common.util.MaterialColorMapUtils;
import com.android.contacts.common.util.MaterialColorMapUtils.MaterialPalette;
import com.android.contacts.common.util.PermissionsUtil;
@@ -182,10 +183,8 @@
import com.android.contacts.widget.MultiShrinkScroller.MultiShrinkScrollerListener;
import com.android.contacts.widget.QuickContactImageView;
import com.android.contactsbind.HelpUtils;
-
import com.google.common.collect.Lists;
-import java.lang.SecurityException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Calendar;
@@ -258,6 +257,7 @@
// Set true in {@link #onCreate} after orientation change for later use in processIntent().
private boolean mIsRecreatedInstance;
+ private boolean mShortcutUsageReported = false;
private boolean mShouldLog;
@@ -1267,6 +1267,7 @@
getIntent().getStringExtra(QuickContact.EXTRA_PRIORITIZED_MIMETYPE);
final Uri oldLookupUri = mLookupUri;
+
if (lookupUri == null) {
finish();
return;
@@ -2613,6 +2614,11 @@
return;
}
+ if (!mIsRecreatedInstance && !mShortcutUsageReported) {
+ mShortcutUsageReported = true;
+ DynamicShortcuts.reportShortcutUsed(QuickContactActivity.this,
+ data.getLookupKey());
+ }
bindContactData(data);
} finally {