Merge "Simplify preview logic"
diff --git a/res/values/strings.xml b/res/values/strings.xml
index d9ac590..bc35005 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -10315,10 +10315,10 @@
     <!-- UI debug setting: force desktop mode summary [CHAR LIMIT=NONE] -->
     <string name="force_desktop_mode_summary">Force experimental desktop mode on secondary displays</string>
 
-    <!-- UI debug setting: Force enable "smart dark" UI rendering feature [CHAR LIMIT=25] -->
-    <string name="hwui_force_dark_title">Force-enable SmartDark</string>
-    <!-- UI debug setting: Force enable "smart dark" UI rendering feature summary [CHAR LIMIT=50] -->
-    <string name="hwui_force_dark_summary">Forces the SmartDark feature to be always-on</string>
+    <!-- UI debug setting: Force enable "smart dark" UI rendering feature [CHAR LIMIT=40] -->
+    <string name="hwui_force_dark_title">Override force-dark</string>
+    <!-- UI debug setting: Force enable "smart dark" UI rendering feature summary [CHAR LIMIT=100] -->
+    <string name="hwui_force_dark_summary">Overrides the force-dark feature to be always-on</string>
 
     <!-- Title for the top level Privacy Settings [CHAR LIMIT=30]-->
     <string name="privacy_dashboard_title">Privacy</string>
diff --git a/src/com/android/settings/accounts/AvatarViewMixin.java b/src/com/android/settings/accounts/AvatarViewMixin.java
index 78750b1..35a3cbf 100644
--- a/src/com/android/settings/accounts/AvatarViewMixin.java
+++ b/src/com/android/settings/accounts/AvatarViewMixin.java
@@ -55,27 +55,37 @@
 
     private static final String METHOD_GET_ACCOUNT_AVATAR = "getAccountAvatar";
     private static final String KEY_AVATAR_BITMAP = "account_avatar";
+    private static final String KEY_ACCOUNT_NAME = "account_name";
+    private static final String EXTRA_ACCOUNT_NAME = "extra.accountName";
     private static final int REQUEST_CODE = 1013;
 
     private final Context mContext;
     private final ImageView mAvatarView;
     private final MutableLiveData<Bitmap> mAvatarImage;
 
+    private String mAccountName;
+
     public AvatarViewMixin(SettingsHomepageActivity activity, ImageView avatarView) {
         mContext = activity.getApplicationContext();
         mAvatarView = avatarView;
         mAvatarView.setOnClickListener(v -> {
-            if (hasAccount()) {
-                //TODO(b/117509285) launch the new page of the MeCard
-            } else {
-                final Intent intent = FeatureFactory.getFactory(mContext)
-                        .getAccountFeatureProvider()
-                        .getAccountSettingsDeeplinkIntent();
+            final Intent intent = FeatureFactory.getFactory(mContext)
+                    .getAccountFeatureProvider()
+                    .getAccountSettingsDeeplinkIntent();
 
-                if (intent != null) {
-                    activity.startActivityForResult(intent, REQUEST_CODE);
-                }
+            if (intent == null) {
+                return;
             }
+
+            if (!TextUtils.isEmpty(mAccountName)) {
+                //TODO(b/117509285) launch the new page of the MeCard
+                intent.putExtra(EXTRA_ACCOUNT_NAME, mAccountName);
+            }
+
+            // Here may have two different UI while start the activity.
+            // It will display adding account UI when device has no any account.
+            // It will display account information page when intent added the specified account.
+            activity.startActivityForResult(intent, REQUEST_CODE);
         });
 
         mAvatarImage = new MutableLiveData<>();
@@ -91,7 +101,7 @@
             return;
         }
         if (hasAccount()) {
-            loadAvatar();
+            loadAccount();
         } else {
             mAvatarView.setImageResource(R.drawable.ic_account_circle_24dp);
         }
@@ -104,7 +114,7 @@
         return (accounts != null) && (accounts.length > 0);
     }
 
-    private void loadAvatar() {
+    private void loadAccount() {
         final String authority = queryProviderAuthority();
         if (TextUtils.isEmpty(authority)) {
             return;
@@ -117,6 +127,7 @@
             final Bundle bundle = mContext.getContentResolver().call(uri,
                     METHOD_GET_ACCOUNT_AVATAR, null /* arg */, null /* extras */);
             final Bitmap bitmap = bundle.getParcelable(KEY_AVATAR_BITMAP);
+            mAccountName = bundle.getString(KEY_ACCOUNT_NAME, "" /* defaultValue */);
             mAvatarImage.postValue(bitmap);
         });
     }
diff --git a/src/com/android/settings/homepage/contextualcards/CardContentProvider.java b/src/com/android/settings/homepage/contextualcards/CardContentProvider.java
index 8088143..e7ede14 100644
--- a/src/com/android/settings/homepage/contextualcards/CardContentProvider.java
+++ b/src/com/android/settings/homepage/contextualcards/CardContentProvider.java
@@ -17,6 +17,7 @@
 package com.android.settings.homepage.contextualcards;
 
 import android.content.ContentProvider;
+import android.content.ContentResolver;
 import android.content.ContentValues;
 import android.content.UriMatcher;
 import android.database.Cursor;
@@ -36,10 +37,15 @@
  */
 public class CardContentProvider extends ContentProvider {
 
-    private static final String TAG = "CardContentProvider";
-
     public static final String CARD_AUTHORITY = "com.android.settings.homepage.CardContentProvider";
 
+    public static final Uri URI = new Uri.Builder()
+                    .scheme(ContentResolver.SCHEME_CONTENT)
+                    .authority(CardContentProvider.CARD_AUTHORITY)
+                    .appendPath(CardDatabaseHelper.CARD_TABLE)
+                    .build();
+
+    private static final String TAG = "CardContentProvider";
     /** URI matcher for ContentProvider queries. */
     private static final UriMatcher URI_MATCHER = new UriMatcher(UriMatcher.NO_MATCH);
     /** URI matcher type for cards table */
diff --git a/src/com/android/settings/homepage/contextualcards/CardDatabaseHelper.java b/src/com/android/settings/homepage/contextualcards/CardDatabaseHelper.java
index b5cdf87..164afdd 100644
--- a/src/com/android/settings/homepage/contextualcards/CardDatabaseHelper.java
+++ b/src/com/android/settings/homepage/contextualcards/CardDatabaseHelper.java
@@ -209,16 +209,19 @@
      * Mark a specific ContextualCard with dismissal flag in the database to indicate that the
      * card has been dismissed.
      *
-     * @param cardName the card name of the ContextualCard which is dismissed by user.
-     * @return updated row number
+     * @param context Context
+     * @param cardName The card name of the ContextualCard which is dismissed by user.
+     * @return The number of rows updated
      */
-    public int markContextualCardAsDismissed(String cardName) {
-        final SQLiteDatabase database = this.getWritableDatabase();
+    public int markContextualCardAsDismissed(Context context, String cardName) {
+        final SQLiteDatabase database = getWritableDatabase();
         final ContentValues values = new ContentValues();
         values.put(CardColumns.CARD_DISMISSED, 1);
         final String selection = CardColumns.NAME + "=?";
         final String[] selectionArgs = {cardName};
         final int rowsUpdated = database.update(CARD_TABLE, values, selection, selectionArgs);
+        database.close();
+        context.getContentResolver().notifyChange(CardContentProvider.URI, null);
         return rowsUpdated;
     }
 }
diff --git a/src/com/android/settings/homepage/contextualcards/ContextualCardLoader.java b/src/com/android/settings/homepage/contextualcards/ContextualCardLoader.java
index adfaf20..c723cfd 100644
--- a/src/com/android/settings/homepage/contextualcards/ContextualCardLoader.java
+++ b/src/com/android/settings/homepage/contextualcards/ContextualCardLoader.java
@@ -24,8 +24,11 @@
 import android.content.ContentResolver;
 import android.content.Context;
 import android.content.pm.PackageManager;
+import android.database.ContentObserver;
 import android.database.Cursor;
 import android.net.Uri;
+import android.os.Handler;
+import android.os.Looper;
 import android.util.Log;
 
 import androidx.annotation.NonNull;
@@ -61,6 +64,19 @@
     }
 
     @Override
+    protected void onStartLoading() {
+        super.onStartLoading();
+        mContext.getContentResolver().registerContentObserver(CardContentProvider.URI,
+                false /*notifyForDescendants*/, mObserver);
+    }
+
+    @Override
+    protected void onStopLoading() {
+        super.onStopLoading();
+        mContext.getContentResolver().unregisterContentObserver(mObserver);
+    }
+
+    @Override
     protected void onDiscardResult(List<ContextualCard> result) {
 
     }
@@ -184,4 +200,14 @@
         }
         return -1L;
     }
+
+    private final ContentObserver mObserver = new ContentObserver(
+            new Handler(Looper.getMainLooper())) {
+        @Override
+        public void onChange(boolean selfChange) {
+            if (isStarted()) {
+                forceLoad();
+            }
+        }
+    };
 }
diff --git a/src/com/android/settings/homepage/contextualcards/ControllerRendererPool.java b/src/com/android/settings/homepage/contextualcards/ControllerRendererPool.java
index 723b344..931bfb7 100644
--- a/src/com/android/settings/homepage/contextualcards/ControllerRendererPool.java
+++ b/src/com/android/settings/homepage/contextualcards/ControllerRendererPool.java
@@ -114,7 +114,7 @@
         if (ConditionContextualCardController.class == clz) {
             return new ConditionContextualCardController(context);
         } else if (SliceContextualCardController.class == clz) {
-            return new SliceContextualCardController();
+            return new SliceContextualCardController(context);
         } else if (LegacySuggestionContextualCardController.class == clz) {
             return new LegacySuggestionContextualCardController(context);
         }
diff --git a/src/com/android/settings/homepage/contextualcards/conditional/ConditionContextualCardController.java b/src/com/android/settings/homepage/contextualcards/conditional/ConditionContextualCardController.java
index 84ceabd..6fcc636 100644
--- a/src/com/android/settings/homepage/contextualcards/conditional/ConditionContextualCardController.java
+++ b/src/com/android/settings/homepage/contextualcards/conditional/ConditionContextualCardController.java
@@ -77,13 +77,13 @@
 
     @Override
     public void onActionClick(ContextualCard contextualCard) {
-
+        final ConditionalContextualCard card = (ConditionalContextualCard) contextualCard;
+        mConditionManager.onActionClick(card.getConditionId());
     }
 
     @Override
     public void onDismissed(ContextualCard contextualCard) {
-        final ConditionalContextualCard card = (ConditionalContextualCard) contextualCard;
-        mConditionManager.onActionClick(card.getConditionId());
+
     }
 
     @Override
@@ -93,8 +93,8 @@
         final boolean isOddNumber = conditionCards.size() % 2 == 1;
         if (isOddNumber) {
             final int lastIndex = conditionCards.size() - 1;
-            final ConditionalContextualCard card = (ConditionalContextualCard) conditionCards.get(
-                    lastIndex);
+            final ConditionalContextualCard card = (ConditionalContextualCard) conditionCards
+                    .get(lastIndex);
             conditionCards.set(lastIndex, card.mutate().setIsHalfWidth(false).build());
         }
 
diff --git a/src/com/android/settings/homepage/contextualcards/conditional/ConditionContextualCardRenderer.java b/src/com/android/settings/homepage/contextualcards/conditional/ConditionContextualCardRenderer.java
index 3405dd2..34f442c 100644
--- a/src/com/android/settings/homepage/contextualcards/conditional/ConditionContextualCardRenderer.java
+++ b/src/com/android/settings/homepage/contextualcards/conditional/ConditionContextualCardRenderer.java
@@ -113,7 +113,7 @@
                         viewContext, MetricsProto.MetricsEvent.ACTION_SETTINGS_CONDITION_BUTTON,
                         card.getMetricsConstant());
                 mControllerRendererPool.getController(mContext, card.getCardType())
-                        .onDismissed(card);
+                        .onActionClick(card);
             });
         } else {
             button.setVisibility(View.GONE);
diff --git a/src/com/android/settings/homepage/contextualcards/slices/SliceContextualCardController.java b/src/com/android/settings/homepage/contextualcards/slices/SliceContextualCardController.java
index 6ab8f40..f1fbc9c 100644
--- a/src/com/android/settings/homepage/contextualcards/slices/SliceContextualCardController.java
+++ b/src/com/android/settings/homepage/contextualcards/slices/SliceContextualCardController.java
@@ -16,9 +16,14 @@
 
 package com.android.settings.homepage.contextualcards.slices;
 
+import android.content.Context;
+
+import com.android.settings.homepage.contextualcards.CardContentProvider;
+import com.android.settings.homepage.contextualcards.CardDatabaseHelper;
 import com.android.settings.homepage.contextualcards.ContextualCard;
 import com.android.settings.homepage.contextualcards.ContextualCardController;
 import com.android.settings.homepage.contextualcards.ContextualCardUpdateListener;
+import com.android.settingslib.utils.ThreadUtils;
 
 /**
  * Card controller for {@link ContextualCard} built as slices.
@@ -27,8 +32,13 @@
 
     private static final String TAG = "SliceCardController";
 
+    private Context mContext;
     private ContextualCardUpdateListener mCardUpdateListener;
 
+    public SliceContextualCardController(Context context) {
+        mContext = context;
+    }
+
     @Override
     public int getCardType() {
         return ContextualCard.CardType.SLICE;
@@ -46,11 +56,14 @@
 
     @Override
     public void onDismissed(ContextualCard card) {
-        //TODO(b/113783548): Mark this card as dismissed in db and reload loader.
+        ThreadUtils.postOnBackgroundThread(() -> {
+            final CardDatabaseHelper dbHelper = CardDatabaseHelper.getInstance(mContext);
+            dbHelper.markContextualCardAsDismissed(mContext, card.getName());
+        });
     }
 
     @Override
     public void setCardUpdateListener(ContextualCardUpdateListener listener) {
-            mCardUpdateListener = listener;
+        mCardUpdateListener = listener;
     }
 }
diff --git a/src/com/android/settings/wifi/qrcode/QrCodeGenerator.java b/src/com/android/settings/wifi/qrcode/QrCodeGenerator.java
new file mode 100644
index 0000000..08fcb10
--- /dev/null
+++ b/src/com/android/settings/wifi/qrcode/QrCodeGenerator.java
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) 2018 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.settings.wifi.qrcode;
+
+import android.graphics.Bitmap;
+import android.graphics.Color;
+
+import com.google.zxing.BarcodeFormat;
+import com.google.zxing.MultiFormatWriter;
+import com.google.zxing.WriterException;
+import com.google.zxing.common.BitMatrix;
+
+public final class QrCodeGenerator {
+    /**
+     * Generates a barcode image with {@code contents}.
+     *
+     * @param contents The contents to encode in the barcode
+     * @param size     The preferred image size in pixels
+     * @return Barcode bitmap
+     */
+    public static Bitmap encodeQrCode(String contents, int size)
+            throws WriterException, IllegalArgumentException {
+        final BitMatrix qrBits = new MultiFormatWriter().encode(contents, BarcodeFormat.QR_CODE,
+                size, size);
+        final Bitmap bitmap = Bitmap.createBitmap(size, size, Bitmap.Config.RGB_565);
+        for (int x = 0; x < size; x++) {
+            for (int y = 0; y < size; y++) {
+                bitmap.setPixel(x, y, qrBits.get(x, y) ? Color.BLACK : Color.WHITE);
+            }
+        }
+        return bitmap;
+    }
+}
diff --git a/tests/robotests/src/com/android/settings/accounts/AvatarViewMixinTest.java b/tests/robotests/src/com/android/settings/accounts/AvatarViewMixinTest.java
index 039d2e2..e074440 100644
--- a/tests/robotests/src/com/android/settings/accounts/AvatarViewMixinTest.java
+++ b/tests/robotests/src/com/android/settings/accounts/AvatarViewMixinTest.java
@@ -18,16 +18,25 @@
 
 import static com.google.common.truth.Truth.assertThat;
 
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.Matchers.anyString;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.never;
 import static org.mockito.Mockito.spy;
 import static org.mockito.Mockito.verify;
 
 import android.accounts.Account;
+import android.content.ContentProvider;
+import android.content.ContentResolver;
 import android.content.Context;
 import android.content.pm.ApplicationInfo;
 import android.content.pm.PackageInfo;
 import android.content.pm.ProviderInfo;
 import android.content.pm.ResolveInfo;
+import android.graphics.Bitmap;
+import android.net.Uri;
+import android.os.Bundle;
 import android.widget.ImageView;
 
 import com.android.settings.homepage.SettingsHomepageActivity;
@@ -44,6 +53,7 @@
 import org.robolectric.annotation.Implementation;
 import org.robolectric.annotation.Implements;
 import org.robolectric.shadow.api.Shadow;
+import org.robolectric.shadows.ShadowContentResolver;
 import org.robolectric.shadows.ShadowPackageManager;
 
 @RunWith(SettingsRobolectricTestRunner.class)
@@ -51,6 +61,7 @@
     private static final String DUMMY_ACCOUNT = "test@domain.com";
     private static final String DUMMY_DOMAIN = "domain.com";
     private static final String DUMMY_AUTHORITY = "authority.domain.com";
+    private static final String METHOD_GET_ACCOUNT_AVATAR = "getAccountAvatar";
 
     private Context mContext;
     private ImageView mImageView;
@@ -128,6 +139,31 @@
         assertThat(avatarViewMixin.queryProviderAuthority()).isEqualTo(DUMMY_AUTHORITY);
     }
 
+    @Test
+    public void callWithGetAccountAvatarMethod_useDummyData_shouldReturnAccountNameAndAvatar() {
+        final ShadowContentResolver shadowContentResolver = Shadow.extract(
+                mContext.getContentResolver());
+        final Uri uri = new Uri.Builder().scheme(ContentResolver.SCHEME_CONTENT).authority(
+                DUMMY_AUTHORITY).build();
+        final ContentProvider mockContentProvider = mock(ContentProvider.class);
+
+        ShadowContentResolver.registerProviderInternal(DUMMY_AUTHORITY, mockContentProvider);
+
+        final Bundle bundle = new Bundle();
+        final Bitmap bitmap = Bitmap.createBitmap(100, 100, Bitmap.Config.ARGB_8888);
+        bundle.putParcelable("account_avatar", bitmap);
+        bundle.putString("account_name", DUMMY_ACCOUNT);
+        doReturn(bundle).when(mockContentProvider).call(anyString(), anyString(),
+                any(Bundle.class));
+
+        final Bundle expectBundle = shadowContentResolver.call(uri, METHOD_GET_ACCOUNT_AVATAR,
+                null /* arg */, null /* extras */);
+
+        final Object object = bundle.getParcelable("account_avatar");
+        assertThat(object instanceof Bitmap).isTrue();
+        assertThat(bundle.getString("account_name")).isEqualTo(DUMMY_ACCOUNT);
+    }
+
     @Implements(value = AccountFeatureProviderImpl.class)
     public static class ShadowAccountFeatureProviderImpl {
 
diff --git a/tests/robotests/src/com/android/settings/applications/appinfo/AppDataUsagePreferenceControllerTest.java b/tests/robotests/src/com/android/settings/applications/appinfo/AppDataUsagePreferenceControllerTest.java
index e77106d..1adc678 100644
--- a/tests/robotests/src/com/android/settings/applications/appinfo/AppDataUsagePreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/applications/appinfo/AppDataUsagePreferenceControllerTest.java
@@ -16,6 +16,8 @@
 
 package com.android.settings.applications.appinfo;
 
+import static com.android.settings.core.FeatureFlags.DATA_USAGE_V2;
+
 import static com.google.common.truth.Truth.assertThat;
 
 import static org.mockito.ArgumentMatchers.any;
@@ -33,6 +35,7 @@
 import android.net.ConnectivityManager;
 import android.net.INetworkStatsSession;
 import android.os.Bundle;
+import android.util.FeatureFlagUtils;
 
 import androidx.loader.app.LoaderManager;
 import androidx.preference.Preference;
@@ -65,6 +68,7 @@
     public void setUp() {
         MockitoAnnotations.initMocks(this);
         mContext = spy(RuntimeEnvironment.application.getApplicationContext());
+        FeatureFlagUtils.setEnabled(mContext, DATA_USAGE_V2, false);
         mController = spy(new AppDataUsagePreferenceController(mContext, "test_key"));
         mController.setParentFragment(mFragment);
     }
diff --git a/tests/robotests/src/com/android/settings/applications/appinfo/AppMemoryPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/applications/appinfo/AppMemoryPreferenceControllerTest.java
index 733e22e..ed77bd9 100644
--- a/tests/robotests/src/com/android/settings/applications/appinfo/AppMemoryPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/applications/appinfo/AppMemoryPreferenceControllerTest.java
@@ -77,11 +77,6 @@
         when(mFragment.getActivity()).thenReturn(mActivity);
     }
 
-    @After
-    public void tearDown() {
-        ShadowUserManager.getShadow().reset();
-    }
-
     @Test
     @Config(qualifiers = "mcc999")
     public void getAvailabilityStatus_developmentSettingsEnabled_shouldReturnAvailable() {
diff --git a/tests/robotests/src/com/android/settings/datausage/DataUsageSummaryTest.java b/tests/robotests/src/com/android/settings/datausage/DataUsageSummaryTest.java
index 49e3e86..d52793e 100644
--- a/tests/robotests/src/com/android/settings/datausage/DataUsageSummaryTest.java
+++ b/tests/robotests/src/com/android/settings/datausage/DataUsageSummaryTest.java
@@ -28,6 +28,7 @@
 import static org.mockito.Mockito.spy;
 import static org.mockito.Mockito.verify;
 
+import android.app.usage.NetworkStatsManager;
 import android.content.Context;
 import android.net.NetworkPolicyManager;
 
@@ -68,6 +69,8 @@
     private SummaryLoader mSummaryLoader;
     @Mock
     private NetworkPolicyManager mNetworkPolicyManager;
+    @Mock
+    private NetworkStatsManager mNetworkStatsManager;
     private Context mContext;
     private FragmentActivity mActivity;
     private SummaryLoader.SummaryProvider mSummaryProvider;
@@ -86,16 +89,12 @@
 
         mContext = RuntimeEnvironment.application;
         mActivity = spy(Robolectric.buildActivity(FragmentActivity.class).get());
+        doReturn(mNetworkStatsManager).when(mActivity).getSystemService(NetworkStatsManager.class);
 
         mSummaryProvider = DataUsageSummary.SUMMARY_PROVIDER_FACTORY
                 .createSummaryProvider(mActivity, mSummaryLoader);
     }
 
-    @After
-    public void tearDown() {
-        ShadowUserManager.getShadow().reset();
-    }
-
     @Test
     public void formatUsage_shouldLookLikeFormatFileSize() {
         SettingsShadowResources.overrideResource(com.android.internal.R.string.fileSizeSuffix,
diff --git a/tests/robotests/src/com/android/settings/development/DevelopmentSettingsDashboardFragmentTest.java b/tests/robotests/src/com/android/settings/development/DevelopmentSettingsDashboardFragmentTest.java
index a3abb07..d2c9b65 100644
--- a/tests/robotests/src/com/android/settings/development/DevelopmentSettingsDashboardFragmentTest.java
+++ b/tests/robotests/src/com/android/settings/development/DevelopmentSettingsDashboardFragmentTest.java
@@ -75,7 +75,6 @@
     @After
     public void tearDown() {
         ShadowEnableDevelopmentSettingWarningDialog.reset();
-        mShadowUserManager.reset();
     }
 
     @Test
diff --git a/tests/robotests/src/com/android/settings/development/DevelopmentSwitchBarControllerTest.java b/tests/robotests/src/com/android/settings/development/DevelopmentSwitchBarControllerTest.java
index 688db76..da0dcaf 100644
--- a/tests/robotests/src/com/android/settings/development/DevelopmentSwitchBarControllerTest.java
+++ b/tests/robotests/src/com/android/settings/development/DevelopmentSwitchBarControllerTest.java
@@ -70,7 +70,6 @@
     @After
     public void tearDown() {
         ShadowUtils.reset();
-        ShadowUserManager.getShadow().reset();
     }
 
     @Test
diff --git a/tests/robotests/src/com/android/settings/homepage/contextualcards/slices/SliceContextualCardControllerTest.java b/tests/robotests/src/com/android/settings/homepage/contextualcards/slices/SliceContextualCardControllerTest.java
new file mode 100644
index 0000000..362e1f5
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/homepage/contextualcards/slices/SliceContextualCardControllerTest.java
@@ -0,0 +1,96 @@
+/*
+ * Copyright (C) 2018 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.settings.homepage.contextualcards.slices;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import android.content.ContentResolver;
+import android.content.ContentValues;
+import android.content.Context;
+import android.database.Cursor;
+import android.net.Uri;
+
+import com.android.settings.homepage.contextualcards.CardContentProvider;
+import com.android.settings.homepage.contextualcards.CardDatabaseHelper;
+import com.android.settings.homepage.contextualcards.ContextualCard;
+import com.android.settings.testutils.SettingsRobolectricTestRunner;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.robolectric.Robolectric;
+import org.robolectric.RuntimeEnvironment;
+import org.robolectric.shadows.ShadowContentResolver;
+
+@RunWith(SettingsRobolectricTestRunner.class)
+public class SliceContextualCardControllerTest {
+
+    private static final String TEST_SLICE_URI = "content://test/test";
+    private static final String TEST_CARD_NAME = "test_card_name";
+
+    private Context mContext;
+    private CardContentProvider mProvider;
+    private ContentResolver mResolver;
+    private SliceContextualCardController mController;
+
+    @Before
+    public void setUp() {
+        mContext = RuntimeEnvironment.application;
+        mProvider = Robolectric.setupContentProvider(CardContentProvider.class);
+        ShadowContentResolver.registerProviderInternal(CardContentProvider.CARD_AUTHORITY,
+                mProvider);
+        mResolver = mContext.getContentResolver();
+        mController = new SliceContextualCardController(mContext);
+    }
+
+    @Test
+    public void onDismissed_cardShouldBeMarkedAsDismissed() {
+        final Uri providerUri = CardContentProvider.URI;
+        final ContextualCard card = new ContextualCard.Builder()
+                .setName(TEST_CARD_NAME)
+                .setCardType(ContextualCard.CardType.SLICE)
+                .setSliceUri(Uri.parse(TEST_SLICE_URI))
+                .build();
+        mResolver.insert(providerUri, generateOneRow());
+
+        mController.onDismissed(card);
+
+        final String[] columns = {CardDatabaseHelper.CardColumns.CARD_DISMISSED};
+        final String selection = CardDatabaseHelper.CardColumns.NAME + "=?";
+        final String[] selectionArgs = {TEST_CARD_NAME};
+        final Cursor cr = mResolver.query(providerUri, columns, selection, selectionArgs, null);
+        cr.moveToFirst();
+        final int qryDismissed = cr.getInt(0);
+        cr.close();
+
+        assertThat(qryDismissed).isEqualTo(1);
+    }
+
+    private ContentValues generateOneRow() {
+        final ContentValues values = new ContentValues();
+        values.put(CardDatabaseHelper.CardColumns.NAME, TEST_CARD_NAME);
+        values.put(CardDatabaseHelper.CardColumns.TYPE, 1);
+        values.put(CardDatabaseHelper.CardColumns.SCORE, 0.9);
+        values.put(CardDatabaseHelper.CardColumns.SLICE_URI, TEST_SLICE_URI);
+        values.put(CardDatabaseHelper.CardColumns.CATEGORY, 2);
+        values.put(CardDatabaseHelper.CardColumns.PACKAGE_NAME, "com.android.settings");
+        values.put(CardDatabaseHelper.CardColumns.APP_VERSION, 10001);
+        values.put(CardDatabaseHelper.CardColumns.CARD_DISMISSED, 0);
+
+        return values;
+    }
+}
diff --git a/tests/robotests/src/com/android/settings/network/telephony/DataUsagePreferenceControllerTest.java b/tests/robotests/src/com/android/settings/network/telephony/DataUsagePreferenceControllerTest.java
index ea6f903..1d91bb8 100644
--- a/tests/robotests/src/com/android/settings/network/telephony/DataUsagePreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/network/telephony/DataUsagePreferenceControllerTest.java
@@ -23,6 +23,7 @@
 import static org.mockito.Mockito.verify;
 
 import android.app.Activity;
+import android.app.usage.NetworkStatsManager;
 import android.content.Context;
 import android.content.Intent;
 import android.provider.Settings;
@@ -48,6 +49,8 @@
 
     @Mock
     private TelephonyManager mTelephonyManager;
+    @Mock
+    private NetworkStatsManager mNetworkStatsManager;
     private DataUsagePreferenceController mController;
     private SwitchPreference mPreference;
     private Context mContext;
@@ -59,6 +62,7 @@
         mContext = spy(Robolectric.setupActivity(Activity.class));
         doReturn(mTelephonyManager).when(mContext).getSystemService(Context.TELEPHONY_SERVICE);
         doReturn(mTelephonyManager).when(mTelephonyManager).createForSubscriptionId(SUB_ID);
+        doReturn(mNetworkStatsManager).when(mContext).getSystemService(NetworkStatsManager.class);
 
         mPreference = new SwitchPreference(mContext);
         mController = new DataUsagePreferenceController(mContext, "data_usage");
diff --git a/tests/robotests/src/com/android/settings/notification/RedactionInterstitialTest.java b/tests/robotests/src/com/android/settings/notification/RedactionInterstitialTest.java
index b62495c..2f273ae 100644
--- a/tests/robotests/src/com/android/settings/notification/RedactionInterstitialTest.java
+++ b/tests/robotests/src/com/android/settings/notification/RedactionInterstitialTest.java
@@ -48,7 +48,6 @@
 
     @After
     public void tearDown() {
-        ShadowUserManager.getShadow().reset();
         ShadowRestrictedLockUtilsInternal.reset();
     }
 
diff --git a/tests/robotests/src/com/android/settings/security/EncryptionStatusPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/security/EncryptionStatusPreferenceControllerTest.java
index 8221b15..c7fdeae 100644
--- a/tests/robotests/src/com/android/settings/security/EncryptionStatusPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/security/EncryptionStatusPreferenceControllerTest.java
@@ -57,11 +57,6 @@
         mPreference = new Preference(mContext);
     }
 
-    @After
-    public void tearDown() {
-        mShadowUserManager.reset();
-    }
-
     @Test
     public void isAvailable_admin_true() {
         mShadowUserManager.setIsAdminUser(true);
diff --git a/tests/robotests/src/com/android/settings/security/RestrictedEncryptionPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/security/RestrictedEncryptionPreferenceControllerTest.java
index 6bd5e1f..8c7eaa5 100644
--- a/tests/robotests/src/com/android/settings/security/RestrictedEncryptionPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/security/RestrictedEncryptionPreferenceControllerTest.java
@@ -63,11 +63,6 @@
         mUserManager = ShadowUserManager.getShadow();
     }
 
-    @After
-    public void tearDown() {
-        mUserManager.reset();
-    }
-
     @Test
     public void isAvailable_noRestriction_shouldReturnTrue() {
         assertThat(mCredentialStoragePreferenceController.isAvailable()).isTrue();
diff --git a/tests/robotests/src/com/android/settings/slices/SlicesDatabaseAccessorTest.java b/tests/robotests/src/com/android/settings/slices/SlicesDatabaseAccessorTest.java
index bebf797..f628c87 100644
--- a/tests/robotests/src/com/android/settings/slices/SlicesDatabaseAccessorTest.java
+++ b/tests/robotests/src/com/android/settings/slices/SlicesDatabaseAccessorTest.java
@@ -90,7 +90,6 @@
 
     @After
     public void cleanUp() {
-        ShadowUserManager.getShadow().reset();
         DatabaseTestUtils.clearDb(mContext);
     }
 
diff --git a/tests/robotests/src/com/android/settings/system/SystemDashboardFragmentTest.java b/tests/robotests/src/com/android/settings/system/SystemDashboardFragmentTest.java
index 5f787a9..2785c66 100644
--- a/tests/robotests/src/com/android/settings/system/SystemDashboardFragmentTest.java
+++ b/tests/robotests/src/com/android/settings/system/SystemDashboardFragmentTest.java
@@ -48,7 +48,6 @@
     @After
     public void tearDown() {
         SettingsShadowResources.reset();
-        ShadowUserManager.getShadow().reset();
     }
 
     @Test
diff --git a/tests/robotests/src/com/android/settings/testutils/shadow/ShadowUserManager.java b/tests/robotests/src/com/android/settings/testutils/shadow/ShadowUserManager.java
index 61278f3..ccfcc2d 100644
--- a/tests/robotests/src/com/android/settings/testutils/shadow/ShadowUserManager.java
+++ b/tests/robotests/src/com/android/settings/testutils/shadow/ShadowUserManager.java
@@ -49,19 +49,6 @@
     private int[] profileIdsForUser = new int[0];
     private boolean mUserSwitchEnabled;
 
-
-    @Resetter
-    public void reset() {
-        mUserInfos.clear();
-        mRestrictions.clear();
-        mUserProfileInfos.clear();
-        mRestrictionSources.clear();
-        mManagedProfiles.clear();
-        mIsQuietModeEnabled = false;
-        mUserSwitchEnabled = false;
-        profileIdsForUser = new int[0];
-    }
-
     public void setUserInfo(int userHandle, UserInfo userInfo) {
         mUserInfos.put(userHandle, userInfo);
     }
@@ -90,7 +77,7 @@
     }
 
     @Implementation
-    public List<UserHandle> getUserProfiles(){
+    public List<UserHandle> getUserProfiles() {
         int[] userIds = getProfileIds(UserHandle.myUserId(), true /* enabledOnly */);
         List<UserHandle> result = new ArrayList<>(userIds.length);
         for (int userId : userIds) {
diff --git a/tests/robotests/src/com/android/settings/users/AddUserWhenLockedPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/users/AddUserWhenLockedPreferenceControllerTest.java
index 2bd12c3..e31dce2 100644
--- a/tests/robotests/src/com/android/settings/users/AddUserWhenLockedPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/users/AddUserWhenLockedPreferenceControllerTest.java
@@ -63,11 +63,6 @@
         mController = new AddUserWhenLockedPreferenceController(mContext, "fake_key");
     }
 
-    @After
-    public void tearDown() {
-        mUserManager.reset();
-    }
-
     @Test
     public void displayPref_NotAdmin_shouldNotDisplay() {
         mUserManager.setUserInfo(0, mUserInfo);
diff --git a/tests/robotests/src/com/android/settings/users/EditUserInfoControllerTest.java b/tests/robotests/src/com/android/settings/users/EditUserInfoControllerTest.java
index 97b3e69..7304688 100644
--- a/tests/robotests/src/com/android/settings/users/EditUserInfoControllerTest.java
+++ b/tests/robotests/src/com/android/settings/users/EditUserInfoControllerTest.java
@@ -105,11 +105,6 @@
         mController = new TestEditUserInfoController();
     }
 
-    @After
-    public void tearDown() {
-        mUserManager.reset();
-    }
-
     @Test
     public void photoControllerOnActivityResult_whenWaiting_isCalled() {
         mController.createDialog(mFragment, mCurrentIcon, "test user",
diff --git a/tests/robotests/src/com/android/settings/users/UserCapabilitiesTest.java b/tests/robotests/src/com/android/settings/users/UserCapabilitiesTest.java
index c8d3685..894def7 100644
--- a/tests/robotests/src/com/android/settings/users/UserCapabilitiesTest.java
+++ b/tests/robotests/src/com/android/settings/users/UserCapabilitiesTest.java
@@ -45,11 +45,6 @@
         mUserManager = ShadowUserManager.getShadow();
     }
 
-    @After
-    public void tearDown() {
-        mUserManager.reset();
-    }
-
     @Test
     public void disallowUserSwitch_restrictionIsSet_true() {
         mUserManager.setUserRestriction(UserHandle.of(UserHandle.myUserId()),
diff --git a/tests/robotests/src/com/android/settings/wifi/qrcode/QrCameraTest.java b/tests/robotests/src/com/android/settings/wifi/qrcode/QrCameraTest.java
index ca74c19..2595bb6 100644
--- a/tests/robotests/src/com/android/settings/wifi/qrcode/QrCameraTest.java
+++ b/tests/robotests/src/com/android/settings/wifi/qrcode/QrCameraTest.java
@@ -30,13 +30,10 @@
 import com.android.settings.R;
 import com.android.settings.testutils.SettingsRobolectricTestRunner;
 
-import com.google.zxing.BarcodeFormat;
 import com.google.zxing.BinaryBitmap;
 import com.google.zxing.LuminanceSource;
 import com.google.zxing.RGBLuminanceSource;
-import com.google.zxing.MultiFormatWriter;
 import com.google.zxing.WriterException;
-import com.google.zxing.common.BitMatrix;
 import com.google.zxing.common.HybridBinarizer;
 
 import java.util.concurrent.CountDownLatch;
@@ -111,36 +108,17 @@
         final String googleUrl = "http://www.google.com";
 
         try {
-            Bitmap bmp = encodeQrCode(googleUrl, 320);
-            int[] intArray = new int[bmp.getWidth() * bmp.getHeight()];
+            final Bitmap bmp = QrCodeGenerator.encodeQrCode(googleUrl, 320);
+            final int[] intArray = new int[bmp.getWidth() * bmp.getHeight()];
             bmp.getPixels(intArray, 0, bmp.getWidth(), 0, 0, bmp.getWidth(), bmp.getHeight());
             LuminanceSource source = new RGBLuminanceSource(bmp.getWidth(), bmp.getHeight(),
                     intArray);
-
-            BinaryBitmap bitmap = new BinaryBitmap(new HybridBinarizer(source));
+            final BinaryBitmap bitmap = new BinaryBitmap(new HybridBinarizer(source));
             mCamera.decodeImage(bitmap);
+            bmp.recycle();
         } catch (WriterException e) {
         }
 
         assertThat(mQrCode).isEqualTo(googleUrl);
     }
-
-    private Bitmap encodeQrCode(String qrCode, int size) throws WriterException {
-        BitMatrix qrBits = null;
-        try {
-            qrBits =
-                    new MultiFormatWriter().encode(qrCode, BarcodeFormat.QR_CODE, size, size, null);
-        } catch (IllegalArgumentException iae) {
-            // Should never reach here.
-        }
-        assertThat(qrBits).isNotNull();
-
-        Bitmap bitmap = Bitmap.createBitmap(size, size, Bitmap.Config.RGB_565);
-        for (int x = 0; x < size; ++x) {
-            for (int y = 0; y < size; ++y) {
-                bitmap.setPixel(x, y, qrBits.get(x, y) ? Color.BLACK : Color.WHITE);
-            }
-        }
-        return bitmap;
-    }
 }