Remove shortcuts update job when experiment is disabled.

Test
manual: verify that shortcuts are shown after setting, clearing then setting
the flag again.

Bug 31682523
Change-Id: Ibe3a306654eb6f89082e3636efa82f54860b1a15
diff --git a/src/com/android/contacts/DynamicShortcuts.java b/src/com/android/contacts/DynamicShortcuts.java
index 72e5fec..f02306c 100644
--- a/src/com/android/contacts/DynamicShortcuts.java
+++ b/src/com/android/contacts/DynamicShortcuts.java
@@ -24,7 +24,6 @@
 import android.content.ContentResolver;
 import android.content.ContentUris;
 import android.content.Context;
-import android.content.Intent;
 import android.content.pm.ShortcutInfo;
 import android.content.pm.ShortcutManager;
 import android.database.Cursor;
@@ -56,8 +55,6 @@
 import java.util.Collections;
 import java.util.List;
 
-import static com.android.contacts.common.list.ShortcutIntentBuilder.INTENT_EXTRA_IGNORE_LAUNCH_ANIMATION;
-
 /**
  * This class creates and updates the dynamic shortcuts displayed on the Nexus launcher for the
  * Contacts app.
@@ -95,17 +92,21 @@
     private int mLongLabelMaxLength = LONG_LABEL_MAX_LENGTH;
     private final int mContentChangeMinUpdateDelay;
     private final int mContentChangeMaxUpdateDelay;
+    private final JobScheduler mJobScheduler;
 
     public DynamicShortcuts(Context context) {
         this(context, context.getContentResolver(), (ShortcutManager)
-                context.getSystemService(Context.SHORTCUT_SERVICE));
+                context.getSystemService(Context.SHORTCUT_SERVICE),
+                (JobScheduler) context.getSystemService(Context.JOB_SCHEDULER_SERVICE));
     }
 
+    @VisibleForTesting
     public DynamicShortcuts(Context context, ContentResolver contentResolver,
-            ShortcutManager shortcutManager) {
+            ShortcutManager shortcutManager, JobScheduler jobScheduler) {
         mContext = context;
         mContentResolver = contentResolver;
         mShortcutManager = shortcutManager;
+        mJobScheduler = jobScheduler;
         mContentChangeMinUpdateDelay = Flags.getInstance(mContext)
                 .getInteger(Experiments.DYNAMIC_MIN_CONTENT_CHANGE_UPDATE_DELAY_MILLIS);
         mContentChangeMaxUpdateDelay = Flags.getInstance(mContext)
@@ -124,7 +125,11 @@
 
     @VisibleForTesting
     void refresh() {
-        mShortcutManager.setDynamicShortcuts(getStrequentShortcuts());
+        final List<ShortcutInfo> shortcuts = getStrequentShortcuts();
+        mShortcutManager.setDynamicShortcuts(shortcuts);
+        if (Log.isLoggable(TAG, Log.DEBUG)) {
+            Log.d(TAG, "set dynamic shortcuts " + shortcuts);
+        }
         updatePinned();
     }
 
@@ -154,6 +159,12 @@
             }
         }
 
+        if (Log.isLoggable(TAG, Log.DEBUG)) {
+            Log.d(TAG, "updating " + updates);
+            Log.d(TAG, "enabling " + enable);
+            Log.d(TAG, "disabling " + removedIds);
+        }
+
         mShortcutManager.updateShortcuts(updates);
         mShortcutManager.enableShortcuts(enable);
         mShortcutManager.disableShortcuts(removedIds,
@@ -332,7 +343,8 @@
         return result;
     }
 
-    private void handleFlagDisabled() {
+    @VisibleForTesting
+    void handleFlagDisabled() {
         mShortcutManager.removeAllDynamicShortcuts();
 
         final List<ShortcutInfo> pinned = mShortcutManager.getPinnedShortcuts();
@@ -342,6 +354,11 @@
         }
         mShortcutManager.disableShortcuts(ids, mContext
                 .getString(R.string.dynamic_shortcut_disabled_message));
+        if (Log.isLoggable(TAG, Log.DEBUG)) {
+            Log.d(TAG, "DynamicShortcuts have been removed.");
+        }
+
+        mJobScheduler.cancel(ContactsJobService.DYNAMIC_SHORTCUTS_JOB_ID);
     }
 
     @VisibleForTesting
@@ -356,12 +373,23 @@
                         JobInfo.TriggerContentUri.FLAG_NOTIFY_FOR_DESCENDANTS))
                 .setTriggerContentUpdateDelay(mContentChangeMinUpdateDelay)
                 .setTriggerContentMaxDelay(mContentChangeMaxUpdateDelay).build();
-        final JobScheduler scheduler = (JobScheduler)
-                mContext.getSystemService(Context.JOB_SCHEDULER_SERVICE);
-        scheduler.schedule(job);
+        mJobScheduler.schedule(job);
     }
 
     public synchronized static void initialize(Context context) {
+        if (Log.isLoggable(TAG, Log.DEBUG)) {
+            final Flags flags = Flags.getInstance(context);
+            Log.d(TAG, "DyanmicShortcuts.initialize\nVERSION >= N_MR1? " +
+                    (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N_MR1) +
+                    "\n" + Experiments.DYNAMIC_SHORTCUTS + " enabled? " +
+                    flags.getBoolean(Experiments.DYNAMIC_SHORTCUTS) +
+                    "\nisJobScheduled? " + isJobScheduled(context) +
+                    "\nminDelay=" +
+                    flags.getInteger(Experiments.DYNAMIC_MIN_CONTENT_CHANGE_UPDATE_DELAY_MILLIS) +
+                    "\nmaxDelay=" +
+                    flags.getInteger(Experiments.DYNAMIC_MAX_CONTENT_CHANGE_UPDATE_DELAY_MILLIS));
+        }
+
         if (Build.VERSION.SDK_INT < Build.VERSION_CODES.N_MR1) return;
 
         final DynamicShortcuts shortcuts = new DynamicShortcuts(context);
@@ -413,6 +441,9 @@
 
         @Override
         protected void onPostExecute(Void aVoid) {
+            if (Log.isLoggable(TAG, Log.DEBUG)) {
+                Log.d(TAG, "ShorcutUpdateTask.onPostExecute");
+            }
             // The shortcuts may have changed so update the job so that we are observing the
             // correct Uris
             mDynamicShortcuts.scheduleUpdateJob();
diff --git a/tests/src/com/android/contacts/DynamicShortcutsTests.java b/tests/src/com/android/contacts/DynamicShortcutsTests.java
index 168b646..106b72a 100644
--- a/tests/src/com/android/contacts/DynamicShortcutsTests.java
+++ b/tests/src/com/android/contacts/DynamicShortcutsTests.java
@@ -52,14 +52,11 @@
 import static org.mockito.Matchers.eq;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.verifyNoMoreInteractions;
 import static org.mockito.Mockito.when;
 
 @TargetApi(Build.VERSION_CODES.N_MR1)
 @SdkSuppress(minSdkVersion = Build.VERSION_CODES.N_MR1)
-// TODO: need to switch to android.support.test.runner.AndroidJUnitRunner for the @SdkSuppress
-// annotation to be respected. So for now we suppress this test to keep it from failing when run
-// by the build system.
-@Suppress
 @SmallTest
 public class DynamicShortcutsTests extends AndroidTestCase {
 
@@ -120,8 +117,7 @@
         when(mockShortcutManager.getPinnedShortcuts()).thenReturn(
                 Collections.singletonList(shortcutFor(1l, "key1", "name1")));
 
-        final DynamicShortcuts sut = new DynamicShortcuts(getContext(), emptyResolver(),
-                mockShortcutManager);
+        final DynamicShortcuts sut = createDynamicShortcuts(emptyResolver(), mockShortcutManager);
 
         sut.updatePinned();
 
@@ -187,8 +183,20 @@
         assertThat(arg.get(2), isShortcutForContact(3l, "starred_2", "Starred Two"));
     }
 
+    public void test_handleFlagDisabled_stopsJob() {
+        final ShortcutManager mockShortcutManager = mock(ShortcutManager.class);
+        final JobScheduler mockJobScheduler = mock(JobScheduler.class);
+        final DynamicShortcuts sut = createDynamicShortcuts(emptyResolver(), mockShortcutManager,
+                mockJobScheduler);
+
+        sut.handleFlagDisabled();
+
+        verify(mockJobScheduler).cancel(eq(ContactsJobService.DYNAMIC_SHORTCUTS_JOB_ID));
+    }
+
+
     public void test_scheduleUpdateJob_schedulesJob() {
-        final DynamicShortcuts sut = createDynamicShortcuts();
+        final DynamicShortcuts sut = new DynamicShortcuts(getContext());
         sut.scheduleUpdateJob();
         assertThat(DynamicShortcuts.isJobScheduled(getContext()), Matchers.is(true));
     }
@@ -266,10 +274,16 @@
         return createDynamicShortcuts(emptyResolver(), mock(ShortcutManager.class));
     }
 
+
     private DynamicShortcuts createDynamicShortcuts(ContentResolver resolver,
             ShortcutManager shortcutManager) {
+        return createDynamicShortcuts(resolver, shortcutManager, mock(JobScheduler.class));
+    }
+
+    private DynamicShortcuts createDynamicShortcuts(ContentResolver resolver,
+            ShortcutManager shortcutManager, JobScheduler jobScheduler) {
         final DynamicShortcuts result = new DynamicShortcuts(getContext(), resolver,
-                shortcutManager);
+                shortcutManager, jobScheduler);
         // Use very long label limits to make checking shortcuts easier to understand
         result.setShortLabelMaxLength(100);
         result.setLongLabelMaxLength(100);