Merge "Display a hardware info dialog when click model number."
diff --git a/res/layout/vpn_dialog.xml b/res/layout/vpn_dialog.xml
index 6822e95..61b0861 100644
--- a/res/layout/vpn_dialog.xml
+++ b/res/layout/vpn_dialog.xml
@@ -20,7 +20,7 @@
     <LinearLayout android:layout_width="match_parent"
             android:layout_height="wrap_content"
             android:orientation="vertical"
-            android:padding="8dp">
+            android:padding="24dp">
 
         <LinearLayout android:id="@+id/editor"
                 android:layout_width="match_parent"
diff --git a/res/values/strings.xml b/res/values/strings.xml
index 0420610..c9a1bf7 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -3759,7 +3759,9 @@
     <!-- On Text & language settings screen, setting summary for the Auto-punctuate setting. -->
     <string name="auto_punctuate_summary">Press Space key twice to insert \u0022.\u0022</string>
     <!-- On Security & location settings screen, setting check box name. Title of the checkbox to set whether password edit fields will show the most recent character typed and then hide it, or just hide it right away.  By hide, I mean mask it out. -->
-    <string name="show_password">Make passwords visible</string>
+    <string name="show_password">Show passwords</string>
+    <!-- On Security & location settings screen. This is a short summary text describing what "Show passwords" setting does -->
+    <string name="show_password_summary">Display characters briefly as you type</string>
     <!-- Warning message about security implications of enabling an input method, displayed as a dialog
          message when the user selects to enable an IME. -->
     <string name="ime_security_warning">This input method may be able to collect
diff --git a/res/values/themes.xml b/res/values/themes.xml
index c961cce..d6df2ab 100644
--- a/res/values/themes.xml
+++ b/res/values/themes.xml
@@ -216,7 +216,6 @@
     </style>
 
     <style name="Theme.ConfirmDeviceCredentials" parent="Theme.SubSettings">
-        <item name="android:windowLightStatusBar">false</item>
         <item name="confirmDeviceCredentialsSideMargin">@dimen/confirm_credentials_side_margin</item>
         <item name="confirmDeviceCredentialsTopMargin">@dimen/confirm_credentials_top_margin</item>
     </style>
diff --git a/res/xml/installed_app_details_ia.xml b/res/xml/installed_app_details_ia.xml
index 5b9bdc7..3e06e39 100644
--- a/res/xml/installed_app_details_ia.xml
+++ b/res/xml/installed_app_details_ia.xml
@@ -23,6 +23,12 @@
         android:selectable="false"
         android:order="-10000"/>
 
+    <com.android.settings.applications.LayoutPreference
+      android:key="action_buttons"
+      android:layout="@layout/app_action_buttons"
+      android:selectable="false"
+      android:order="-9999"/>
+
     <Preference
         android:key="notification_settings"
         android:title="@string/notifications_label"
diff --git a/res/xml/security_settings_misc.xml b/res/xml/security_settings_misc.xml
index 544769d..04272df 100644
--- a/res/xml/security_settings_misc.xml
+++ b/res/xml/security_settings_misc.xml
@@ -26,8 +26,10 @@
             <intent android:action="android.settings.LOCATION_SOURCE_SETTINGS"/>
         </Preference>
 
-        <SwitchPreference android:key="show_password"
-                android:title="@string/show_password"/>
+        <SwitchPreference
+            android:key="show_password"
+            android:title="@string/show_password"
+            android:summary="@string/show_password_summary"/>
 
     </PreferenceCategory>
 
diff --git a/src/com/android/settings/ChooseLockGeneric.java b/src/com/android/settings/ChooseLockGeneric.java
index 017a348..3e9304d 100644
--- a/src/com/android/settings/ChooseLockGeneric.java
+++ b/src/com/android/settings/ChooseLockGeneric.java
@@ -166,16 +166,6 @@
                     ChooseLockSettingsHelper.EXTRA_KEY_FOR_FINGERPRINT, false);
             mForChangeCredRequiredForBoot = getArguments() != null && getArguments().getBoolean(
                     ChooseLockSettingsHelper.EXTRA_KEY_FOR_CHANGE_CRED_REQUIRED_FOR_BOOT);
-            if (mIsSetNewPassword) {
-                // In ACTION_SET_NEW_PARENT_PROFILE_PASSWORD or ACTION_SET_NEW_PASSWORD, the user
-                // will be asked to confirm the password if one has been set.
-                // On fingerprint supported device, fingerprint options are represented in the
-                // options. If the user chooses to skip fingerprint setup, ChooseLockGeneric is
-                // relaunched to only show options without fingerprint. In this case, we shouldn't
-                // ask the user to confirm the password again.
-                mPasswordConfirmed = getActivity().getIntent().getBooleanExtra(
-                        PASSWORD_CONFIRMED, false);
-            }
 
             if (savedInstanceState != null) {
                 mPasswordConfirmed = savedInstanceState.getBoolean(PASSWORD_CONFIRMED);
@@ -246,11 +236,12 @@
                 showFactoryResetProtectionWarningDialog(key);
                 return true;
             } else if (KEY_SKIP_FINGERPRINT.equals(key)) {
-                Intent chooseLockGenericIntent = new Intent(getActivity(), ChooseLockGeneric.class);
+                Intent chooseLockGenericIntent = new Intent(getActivity(),
+                    ChooseLockGeneric.InternalActivity.class);
                 chooseLockGenericIntent.setAction(getIntent().getAction());
                 // Forward the target user id to  ChooseLockGeneric.
                 chooseLockGenericIntent.putExtra(Intent.EXTRA_USER_ID, mUserId);
-                chooseLockGenericIntent.putExtra(PASSWORD_CONFIRMED, mPasswordConfirmed);
+                chooseLockGenericIntent.putExtra(CONFIRM_CREDENTIALS, !mPasswordConfirmed);
                 startActivityForResult(chooseLockGenericIntent, SKIP_FINGERPRINT_REQUEST);
                 return true;
             } else {
diff --git a/src/com/android/settings/applications/InstalledAppDetails.java b/src/com/android/settings/applications/InstalledAppDetails.java
index c443e73..da6bbc0 100755
--- a/src/com/android/settings/applications/InstalledAppDetails.java
+++ b/src/com/android/settings/applications/InstalledAppDetails.java
@@ -16,8 +16,6 @@
 
 package com.android.settings.applications;
 
-import static com.android.settingslib.RestrictedLockUtils.EnforcedAdmin;
-
 import android.Manifest.permission;
 import android.app.Activity;
 import android.app.ActivityManager;
@@ -68,7 +66,6 @@
 import android.view.MenuInflater;
 import android.view.MenuItem;
 import android.view.View;
-import android.view.View.OnClickListener;
 import android.view.ViewGroup;
 import android.webkit.IWebViewUpdateService;
 import android.widget.Button;
@@ -115,6 +112,8 @@
 import java.util.HashSet;
 import java.util.List;
 
+import static com.android.settingslib.RestrictedLockUtils.EnforcedAdmin;
+
 /**
  * Activity to display application information from Settings. This activity presents
  * extended information associated with a package like code, data, total size, permissions
@@ -148,7 +147,7 @@
     private static final int DLG_SPECIAL_DISABLE = DLG_BASE + 3;
 
     private static final String KEY_HEADER = "header_view";
-    private static final String KEY_FOOTER = "header_footer";
+    private static final String KEY_ACTION_BUTTONS = "action_buttons";
     private static final String KEY_NOTIFICATION = "notification_settings";
     private static final String KEY_STORAGE = "storage_settings";
     private static final String KEY_PERMISSION = "permission_settings";
@@ -165,7 +164,7 @@
     private boolean mInitialized;
     private boolean mShowUninstalled;
     private LayoutPreference mHeader;
-    private LayoutPreference mFooter;
+    private LayoutPreference mActionButtons;
     private Button mUninstallButton;
     private boolean mUpdatedSysApp = false;
     private Button mForceStopButton;
@@ -325,13 +324,13 @@
         super.onCreate(icicle);
         final Activity activity = getActivity();
 
+        if (!ensurePackageInfoAvailable(activity)) {
+            return;
+        }
+
         setHasOptionsMenu(true);
         addPreferencesFromResource(R.xml.installed_app_details_ia);
         addDynamicPrefs();
-        mFooter = new LayoutPreference(getPrefContext(), R.layout.app_action_buttons);
-        mFooter.setOrder(-9999);
-        mFooter.setKey(KEY_FOOTER);
-        getPreferenceScreen().addPreference(mFooter);
         if (Utils.isBandwidthControlEnabled()) {
             INetworkStatsService statsService = INetworkStatsService.Stub.asInterface(
                     ServiceManager.getService(Context.NETWORK_STATS_SERVICE));
@@ -390,6 +389,7 @@
         }
         final Activity activity = getActivity();
         mHeader = (LayoutPreference) findPreference(KEY_HEADER);
+        mActionButtons = (LayoutPreference) findPreference(KEY_ACTION_BUTTONS);
         FeatureFactory.getFactory(activity)
             .getApplicationFeatureProvider(activity)
             .newAppHeaderController(this, mHeader.findViewById(R.id.app_snippet))
@@ -434,10 +434,27 @@
         refreshUi();
     }
 
+    /**
+     * Ensures the {@link PackageInfo} is available to proceed. If it's not available, the fragment
+     * will finish.
+     *
+     * @return true if packageInfo is available.
+     */
+    @VisibleForTesting(otherwise = VisibleForTesting.PRIVATE)
+    boolean ensurePackageInfoAvailable(Activity activity) {
+        if (mPackageInfo == null) {
+            mFinishing = true;
+            Log.w(LOG_TAG, "Package info not available. Is this package already uninstalled?");
+            activity.finishAndRemoveTask();
+            return false;
+        }
+        return true;
+    }
+
     private void prepareUninstallAndStop() {
-        mForceStopButton = (Button) mFooter.findViewById(R.id.right_button);
+        mForceStopButton = (Button) mActionButtons.findViewById(R.id.right_button);
         mForceStopButton.setText(R.string.force_stop);
-        mUninstallButton = (Button) mFooter.findViewById(R.id.left_button);
+        mUninstallButton = (Button) mActionButtons.findViewById(R.id.left_button);
         mForceStopButton.setEnabled(false);
     }
 
diff --git a/src/com/android/settings/deviceinfo/storage/SecondaryUserController.java b/src/com/android/settings/deviceinfo/storage/SecondaryUserController.java
index a5e8373..41800a2 100644
--- a/src/com/android/settings/deviceinfo/storage/SecondaryUserController.java
+++ b/src/com/android/settings/deviceinfo/storage/SecondaryUserController.java
@@ -97,7 +97,7 @@
     @Override
     public void displayPreference(PreferenceScreen screen) {
         if (mStoragePreference == null) {
-            mStoragePreference = new StorageItemPreferenceAlternate(mContext);
+            mStoragePreference = new StorageItemPreferenceAlternate(screen.getContext());
 
             PreferenceGroup group =
                     (PreferenceGroup) screen.findPreference(TARGET_PREFERENCE_GROUP_KEY);
diff --git a/src/com/android/settings/deviceinfo/storage/UserProfileController.java b/src/com/android/settings/deviceinfo/storage/UserProfileController.java
index 5da9fec..963784d 100644
--- a/src/com/android/settings/deviceinfo/storage/UserProfileController.java
+++ b/src/com/android/settings/deviceinfo/storage/UserProfileController.java
@@ -60,7 +60,7 @@
 
     @Override
     public void displayPreference(PreferenceScreen screen) {
-        mStoragePreference = new StorageItemPreferenceAlternate(mContext);
+        mStoragePreference = new StorageItemPreferenceAlternate(screen.getContext());
         mStoragePreference.setOrder(mPreferenceOrder);
         mStoragePreference.setKey(PREFERENCE_KEY_BASE + mUser.id);
         mStoragePreference.setTitle(mUser.name);
diff --git a/src/com/android/settings/vpn2/LegacyVpnPreference.java b/src/com/android/settings/vpn2/LegacyVpnPreference.java
index c1550e2..a4d7221 100644
--- a/src/com/android/settings/vpn2/LegacyVpnPreference.java
+++ b/src/com/android/settings/vpn2/LegacyVpnPreference.java
@@ -34,7 +34,7 @@
 
     LegacyVpnPreference(Context context) {
         super(context, null /* attrs */);
-        setIcon(R.mipmap.ic_launcher_settings);
+        setIcon(R.drawable.ic_settings_24dp);
     }
 
     public VpnProfile getProfile() {
diff --git a/src/com/android/settings/widget/VideoPreference.java b/src/com/android/settings/widget/VideoPreference.java
index c8786dc..e06ef56 100644
--- a/src/com/android/settings/widget/VideoPreference.java
+++ b/src/com/android/settings/widget/VideoPreference.java
@@ -62,6 +62,7 @@
                     .build();
             mMediaPlayer = MediaPlayer.create(mContext, mVideoPath);
             if (mMediaPlayer != null && mMediaPlayer.getDuration() > 0) {
+                setVisible(true);
                 setLayoutResource(R.layout.video_preference);
 
                 mPreviewResource = attributes.getResourceId(
@@ -71,6 +72,8 @@
 
                 mMediaPlayer.setOnPreparedListener(mediaPlayer -> mediaPlayer.setLooping(true));
                 mAnimationAvailable = true;
+            } else {
+                setVisible(false);
             }
         } catch (Exception e) {
             Log.w(TAG, "Animation resource not found. Will not show animation.");
diff --git a/tests/app/Android.mk b/tests/app/Android.mk
index 381006a..c0c0ccf 100644
--- a/tests/app/Android.mk
+++ b/tests/app/Android.mk
@@ -14,6 +14,7 @@
     espresso-contrib-nodep \
     espresso-intents-nodep \
     ub-uiautomator \
+    truth-prebuilt \
     legacy-android-test
 
 # Include all test java files.
diff --git a/tests/app/src/com/android/settings/ChooseLockGenericTest.java b/tests/app/src/com/android/settings/ChooseLockGenericTest.java
new file mode 100644
index 0000000..dee6697
--- /dev/null
+++ b/tests/app/src/com/android/settings/ChooseLockGenericTest.java
@@ -0,0 +1,235 @@
+/*
+ * Copyright (C) 2017 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;
+
+import android.app.Activity;
+import android.app.admin.DevicePolicyManager;
+import android.content.Context;
+import android.content.Intent;
+import android.content.pm.PackageManager;
+import android.support.test.filters.MediumTest;
+import android.support.test.rule.ActivityTestRule;
+import android.support.test.runner.AndroidJUnit4;
+import android.support.test.runner.lifecycle.ActivityLifecycleMonitorRegistry;
+import android.support.test.runner.lifecycle.Stage;
+import android.support.test.uiautomator.UiDevice;
+import android.support.test.uiautomator.UiObject;
+import android.support.test.uiautomator.UiSelector;
+
+import android.text.format.DateUtils;
+import android.view.KeyEvent;
+
+import com.android.settings.R;
+
+import java.util.Collection;
+
+import org.junit.After;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import static android.support.test.InstrumentationRegistry.getInstrumentation;
+import static com.google.common.truth.Truth.assertThat;
+import static org.junit.Assert.assertTrue;
+
+/**
+ * Tests for {@link ChooseLockGenericTest}
+ *
+ * m SettingsTests &&
+ * adb install \
+ * -r -g  ${ANDROID_PRODUCT_OUT}/data/app/SettingsTests/SettingsTests.apk &&
+ * adb shell am instrument -e class com.android.settings.ChooseLockGenericTest \
+ * -w com.android.settings.tests/android.support.test.runner.AndroidJUnitRunner
+ */
+@RunWith(AndroidJUnit4.class)
+@MediumTest
+public class ChooseLockGenericTest {
+    private static final long TIMEOUT = 5 * DateUtils.SECOND_IN_MILLIS;
+    private static final Intent PHISHING_ATTACK_INTENT = new Intent()
+            .putExtra("confirm_credentials", false)
+            .putExtra("password_confirmed", true);
+
+    private UiDevice mDevice;
+    private Context mTargetContext;
+    private String mSettingPackage;
+    private PackageManager mPackageManager;
+    @Rule
+    public ActivityTestRule<ChooseLockGeneric> mChooseLockGenericActivityRule =
+            new ActivityTestRule<>(
+                    ChooseLockGeneric.class,
+                    true /* enable touch at launch */,
+                    false /* don't launch at every test */);
+
+    @Before
+    public void setUp() throws Exception {
+        mDevice = UiDevice.getInstance(getInstrumentation());
+        mTargetContext = getInstrumentation().getTargetContext();
+        mSettingPackage = mTargetContext.getPackageName();
+        mPackageManager = mTargetContext.getPackageManager();
+
+        setPassword();
+    }
+
+    @After
+    public void tearDown() throws Exception {
+        clearPassword();
+    }
+
+    @Test
+    public void testConfirmLockPasswordShown_deviceWithPassword() throws Exception, Throwable {
+        // GIVEN a PIN password is set on this device at set up.
+        // WHEN ChooseLockGeneric is launched with no extras.
+        mChooseLockGenericActivityRule.launchActivity(null /* No extras */);
+        // THEN ConfirmLockPassword.InternalActivity is shown.
+        assertThat(getCurrentActivity()).isInstanceOf(ConfirmLockPassword.InternalActivity.class);
+    }
+
+    @Test
+    public void testConfirmLockPasswordShown_deviceWithPassword_phishingAttack()
+            throws Exception, Throwable {
+        // GIVEN a PIN password is set on this device at set up.
+        // WHEN ChooseLockGeneric is launched with extras to by-pass lock password confirmation.
+        mChooseLockGenericActivityRule.launchActivity(PHISHING_ATTACK_INTENT);
+        // THEN ConfirmLockPassword.InternalActivity is still shown.
+        assertThat(getCurrentActivity()).isInstanceOf(ConfirmLockPassword.InternalActivity.class);
+    }
+
+    private Activity getCurrentActivity() throws Throwable {
+        getInstrumentation().waitForIdleSync();
+        final Activity[] activity = new Activity[1];
+        getInstrumentation().runOnMainSync(new Runnable() {
+            @Override
+            public void run() {
+                Collection<Activity> activities = ActivityLifecycleMonitorRegistry.getInstance()
+                        .getActivitiesInStage(Stage.RESUMED);
+                activity[0] = activities.iterator().next();
+            }
+        });
+        return activity[0];
+    }
+
+    private void launchNewPassword() throws Exception {
+        Intent newPasswordIntent = new Intent(DevicePolicyManager.ACTION_SET_NEW_PASSWORD)
+                .setPackage(mSettingPackage)
+                .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+        getInstrumentation().getContext().startActivity(newPasswordIntent);
+        mDevice.waitForIdle();
+    }
+
+    /** Sets a PIN password, 12345, for testing. */
+    private void setPassword() throws Exception {
+        launchNewPassword();
+
+        if (mPackageManager.hasSystemFeature(PackageManager.FEATURE_FINGERPRINT)) {
+            // Set "lock_none", but it actually means we don't want to enroll a fingerprint.
+            UiObject view = new UiObject(
+                    new UiSelector().resourceId(mSettingPackage + ":id/lock_none"));
+            assertTrue("lock_none", view.waitForExists(TIMEOUT));
+            view.click();
+            mDevice.waitForIdle();
+        }
+
+        // Pick PIN from the option list
+        UiObject view = new UiObject(new UiSelector()
+                .resourceId(mSettingPackage + ":id/lock_pin"));
+        assertTrue("lock_pin", view.waitForExists(TIMEOUT));
+        view.click();
+        mDevice.waitForIdle();
+
+        // Ignore any interstitial options
+        view = new UiObject(new UiSelector()
+                .resourceId(mSettingPackage + ":id/encrypt_dont_require_password"));
+        if (view.waitForExists(TIMEOUT)) {
+            view.click();
+            mDevice.waitForIdle();
+        }
+
+        // Yes, we really want to
+        view = new UiObject(new UiSelector()
+                .resourceId(mSettingPackage + ":id/next_button"));
+        if (view.waitForExists(TIMEOUT)) {
+            view.click();
+            mDevice.waitForIdle();
+        }
+
+        // Set our PIN
+        view = new UiObject(new UiSelector()
+                .resourceId(mSettingPackage + ":id/password_entry"));
+        assertTrue("password_entry", view.waitForExists(TIMEOUT));
+
+        // Enter it twice to confirm
+        enterTestPin();
+        enterTestPin();
+
+        mDevice.pressBack();
+    }
+
+    /** Clears the previous set PIN password. */
+    private void clearPassword() throws Exception {
+        launchNewPassword();
+
+        // Enter current PIN
+        UiObject view = new UiObject(
+                new UiSelector().resourceId(mSettingPackage + ":id/password_entry"));
+        if (!view.waitForExists(TIMEOUT)) {
+            // Odd, maybe there is a crash dialog showing; try dismissing it
+            mDevice.pressBack();
+            mDevice.waitForIdle();
+
+            assertTrue("password_entry", view.waitForExists(TIMEOUT));
+        }
+
+        enterTestPin();
+
+        // Set back to "none"
+        view = new UiObject(new UiSelector().resourceId(mSettingPackage + ":id/lock_none"));
+        assertTrue("lock_none", view.waitForExists(TIMEOUT));
+        view.click();
+        mDevice.waitForIdle();
+
+        // Yes, we really want "none" if prompted again
+        view = new UiObject(new UiSelector().resourceId(mSettingPackage + ":id/lock_none"));
+        if (view.waitForExists(TIMEOUT)) {
+            view.click();
+            mDevice.waitForIdle();
+        }
+
+        // Yes, we really want to
+        view = new UiObject(new UiSelector()
+                .resourceId("android:id/button1"));
+        if (view.waitForExists(TIMEOUT)) {
+            view.click();
+            mDevice.waitForIdle();
+        }
+
+        mDevice.pressBack();
+    }
+
+    private void enterTestPin() throws Exception {
+        mDevice.waitForIdle();
+        mDevice.pressKeyCode(KeyEvent.KEYCODE_1);
+        mDevice.pressKeyCode(KeyEvent.KEYCODE_2);
+        mDevice.pressKeyCode(KeyEvent.KEYCODE_3);
+        mDevice.pressKeyCode(KeyEvent.KEYCODE_4);
+        mDevice.pressKeyCode(KeyEvent.KEYCODE_5);
+        mDevice.waitForIdle();
+        mDevice.pressEnter();
+        mDevice.waitForIdle();
+    }
+}
diff --git a/tests/robotests/src/com/android/settings/applications/InstalledAppDetailsTest.java b/tests/robotests/src/com/android/settings/applications/InstalledAppDetailsTest.java
index 4fe6293..b0cd8d5 100644
--- a/tests/robotests/src/com/android/settings/applications/InstalledAppDetailsTest.java
+++ b/tests/robotests/src/com/android/settings/applications/InstalledAppDetailsTest.java
@@ -16,12 +16,8 @@
 
 package com.android.settings.applications;
 
-import static com.google.common.truth.Truth.assertThat;
 
-import static org.mockito.Matchers.anyString;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.when;
-
+import android.app.Activity;
 import android.app.admin.DevicePolicyManager;
 import android.content.Context;
 import android.content.pm.ApplicationInfo;
@@ -44,6 +40,14 @@
 import org.robolectric.annotation.Config;
 import org.robolectric.util.ReflectionHelpers;
 
+import static com.google.common.truth.Truth.assertThat;
+import static org.mockito.Matchers.anyString;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+
 @RunWith(SettingsRobolectricTestRunner.class)
 @Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
 public final class InstalledAppDetailsTest {
@@ -51,24 +55,27 @@
     @Mock(answer = Answers.RETURNS_DEEP_STUBS)
     private UserManager mUserManager;
     @Mock
+    private Activity mActivity;
+    @Mock
     private DevicePolicyManager mDevicePolicyManager;
 
+    private InstalledAppDetails mAppDetail;
+
     @Before
     public void setUp() {
         MockitoAnnotations.initMocks(this);
+        mAppDetail = new InstalledAppDetails();
     }
 
     @Test
     public void getInstallationStatus_notInstalled_shouldReturnUninstalled() {
-        final InstalledAppDetails mAppDetail = new InstalledAppDetails();
 
         assertThat(mAppDetail.getInstallationStatus(new ApplicationInfo()))
-            .isEqualTo(R.string.not_installed);
+                .isEqualTo(R.string.not_installed);
     }
 
     @Test
     public void getInstallationStatus_enabled_shouldReturnInstalled() {
-        final InstalledAppDetails mAppDetail = new InstalledAppDetails();
         final ApplicationInfo info = new ApplicationInfo();
         info.flags = ApplicationInfo.FLAG_INSTALLED;
         info.enabled = true;
@@ -78,7 +85,6 @@
 
     @Test
     public void getInstallationStatus_disabled_shouldReturnDisabled() {
-        final InstalledAppDetails mAppDetail = new InstalledAppDetails();
         final ApplicationInfo info = new ApplicationInfo();
         info.flags = ApplicationInfo.FLAG_INSTALLED;
         info.enabled = false;
@@ -90,7 +96,6 @@
     public void shouldShowUninstallForAll_installForOneOtherUserOnly_shouldReturnTrue() {
         when(mDevicePolicyManager.packageHasActiveAdmins(anyString())).thenReturn(false);
         when(mUserManager.getUsers().size()).thenReturn(2);
-        final InstalledAppDetails mAppDetail = new InstalledAppDetails();
         ReflectionHelpers.setField(mAppDetail, "mDpm", mDevicePolicyManager);
         ReflectionHelpers.setField(mAppDetail, "mUserManager", mUserManager);
         final ApplicationInfo info = new ApplicationInfo();
@@ -107,7 +112,6 @@
     public void shouldShowUninstallForAll_installForSelfOnly_shouldReturnFalse() {
         when(mDevicePolicyManager.packageHasActiveAdmins(anyString())).thenReturn(false);
         when(mUserManager.getUsers().size()).thenReturn(2);
-        final InstalledAppDetails mAppDetail = new InstalledAppDetails();
         ReflectionHelpers.setField(mAppDetail, "mDpm", mDevicePolicyManager);
         ReflectionHelpers.setField(mAppDetail, "mUserManager", mUserManager);
         final ApplicationInfo info = new ApplicationInfo();
@@ -139,6 +143,22 @@
 
         assertThat(InstalledAppDetails.getStorageSummary(context, stats, false))
                 .isEqualTo("1.00B used in Internal storage");
+    }
 
+    @Test
+    public void launchFragment_hasNoPackageInfo_shouldFinish() {
+        ReflectionHelpers.setField(mAppDetail, "mPackageInfo", null);
+
+        assertThat(mAppDetail.ensurePackageInfoAvailable(mActivity)).isFalse();
+        verify(mActivity).finishAndRemoveTask();
+    }
+
+    @Test
+    public void launchFragment_hasPackageInfo_shouldReturnTrue() {
+        final PackageInfo packageInfo = mock(PackageInfo.class);
+        ReflectionHelpers.setField(mAppDetail, "mPackageInfo", packageInfo);
+
+        assertThat(mAppDetail.ensurePackageInfoAvailable(mActivity)).isTrue();
+        verify(mActivity, never()).finishAndRemoveTask();
     }
 }
diff --git a/tests/robotests/src/com/android/settings/applications/defaultapps/DefaultAutoFillPickerTest.java b/tests/robotests/src/com/android/settings/applications/defaultapps/DefaultAutoFillPickerTest.java
index f2cf729..1ee18cf 100644
--- a/tests/robotests/src/com/android/settings/applications/defaultapps/DefaultAutoFillPickerTest.java
+++ b/tests/robotests/src/com/android/settings/applications/defaultapps/DefaultAutoFillPickerTest.java
@@ -24,6 +24,7 @@
 import com.android.settings.SettingsRobolectricTestRunner;
 import com.android.settings.TestConfig;
 import com.android.settings.applications.PackageManagerWrapper;
+import com.android.settings.testutils.FakeFeatureFactory;
 
 import org.junit.Before;
 import org.junit.Test;
@@ -60,6 +61,7 @@
     @Before
     public void setUp() {
         MockitoAnnotations.initMocks(this);
+        FakeFeatureFactory.setupForTest(mActivity);
         when(mActivity.getSystemService(Context.USER_SERVICE)).thenReturn(mUserManager);
         mPicker = spy(new DefaultAutoFillPicker());
         mPicker.onAttach((Context) mActivity);
diff --git a/tests/robotests/src/com/android/settings/deviceinfo/storage/SecondaryUserControllerTest.java b/tests/robotests/src/com/android/settings/deviceinfo/storage/SecondaryUserControllerTest.java
index 7222f53..c8f3069 100644
--- a/tests/robotests/src/com/android/settings/deviceinfo/storage/SecondaryUserControllerTest.java
+++ b/tests/robotests/src/com/android/settings/deviceinfo/storage/SecondaryUserControllerTest.java
@@ -55,6 +55,10 @@
     private static final String TARGET_PREFERENCE_GROUP_KEY = "pref_secondary_users";
     @Mock
     private UserManagerWrapper mUserManager;
+    @Mock
+    private PreferenceScreen mScreen;
+    @Mock
+    private PreferenceGroup mGroup;
 
     private Context mContext;
     private SecondaryUserController mController;
@@ -66,19 +70,19 @@
         mContext = RuntimeEnvironment.application;
         mPrimaryUser = new UserInfo();
         mController = new SecondaryUserController(mContext, mPrimaryUser);
+
+        when(mScreen.getContext()).thenReturn(mContext);
+        when(mScreen.findPreference(anyString())).thenReturn(mGroup);
+        when(mGroup.getKey()).thenReturn(TARGET_PREFERENCE_GROUP_KEY);
     }
 
     @Test
     public void controllerAddsSecondaryUser() throws Exception {
         mPrimaryUser.name = TEST_NAME;
-        PreferenceScreen screen = mock(PreferenceScreen.class);
-        PreferenceGroup group = mock(PreferenceGroup.class);
-        when(screen.findPreference(anyString())).thenReturn(group);
-        when(group.getKey()).thenReturn(TARGET_PREFERENCE_GROUP_KEY);
-        mController.displayPreference(screen);
+        mController.displayPreference(mScreen);
 
         final ArgumentCaptor<Preference> argumentCaptor = ArgumentCaptor.forClass(Preference.class);
-        verify(group).addPreference(argumentCaptor.capture());
+        verify(mGroup).addPreference(argumentCaptor.capture());
         Preference preference = argumentCaptor.getValue();
         assertThat(preference.getTitle()).isEqualTo(TEST_NAME);
     }
@@ -86,15 +90,11 @@
     @Test
     public void controllerUpdatesSummaryOfNewPreference() throws Exception {
         mPrimaryUser.name = TEST_NAME;
-        PreferenceScreen screen = mock(PreferenceScreen.class);
-        PreferenceGroup group = mock(PreferenceGroup.class);
-        when(screen.findPreference(anyString())).thenReturn(group);
-        when(group.getKey()).thenReturn(TARGET_PREFERENCE_GROUP_KEY);
-        mController.displayPreference(screen);
+        mController.displayPreference(mScreen);
         mController.setSize(10L);
         final ArgumentCaptor<Preference> argumentCaptor = ArgumentCaptor.forClass(Preference.class);
 
-        verify(group).addPreference(argumentCaptor.capture());
+        verify(mGroup).addPreference(argumentCaptor.capture());
 
         Preference preference = argumentCaptor.getValue();
         assertThat(preference.getSummary()).isEqualTo("10.00B");
@@ -153,11 +153,7 @@
     public void controllerUpdatesPreferenceOnAcceptingResult() throws Exception {
         mPrimaryUser.name = TEST_NAME;
         mPrimaryUser.id = 10;
-        PreferenceScreen screen = mock(PreferenceScreen.class);
-        PreferenceGroup group = mock(PreferenceGroup.class);
-        when(screen.findPreference(anyString())).thenReturn(group);
-        when(group.getKey()).thenReturn(TARGET_PREFERENCE_GROUP_KEY);
-        mController.displayPreference(screen);
+        mController.displayPreference(mScreen);
         StorageAsyncLoader.AppsStorageResult userResult =
                 new StorageAsyncLoader.AppsStorageResult();
         SparseArray<StorageAsyncLoader.AppsStorageResult> result = new SparseArray<>();
@@ -166,7 +162,7 @@
 
         mController.handleResult(result);
         final ArgumentCaptor<Preference> argumentCaptor = ArgumentCaptor.forClass(Preference.class);
-        verify(group).addPreference(argumentCaptor.capture());
+        verify(mGroup).addPreference(argumentCaptor.capture());
         Preference preference = argumentCaptor.getValue();
 
         assertThat(preference.getSummary()).isEqualTo("99.00B");
diff --git a/tests/robotests/src/com/android/settings/deviceinfo/storage/UserProfileControllerTest.java b/tests/robotests/src/com/android/settings/deviceinfo/storage/UserProfileControllerTest.java
index 2cd4f76..ed49da4 100644
--- a/tests/robotests/src/com/android/settings/deviceinfo/storage/UserProfileControllerTest.java
+++ b/tests/robotests/src/com/android/settings/deviceinfo/storage/UserProfileControllerTest.java
@@ -21,6 +21,7 @@
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.spy;
 import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
 
 import android.content.Context;
 import android.content.Intent;
@@ -53,6 +54,8 @@
 
     @Mock
     private UserManagerWrapper mUserManager;
+    @Mock
+    private PreferenceScreen mScreen;
 
     private Context mContext;
     private UserProfileController mController;
@@ -64,17 +67,17 @@
         mContext = spy(RuntimeEnvironment.application);
         mPrimaryProfile = new UserInfo();
         mController = new UserProfileController(mContext, mPrimaryProfile, 0);
+        when(mScreen.getContext()).thenReturn(mContext);
     }
 
     @Test
     public void controllerAddsPrimaryProfilePreference() throws Exception {
         mPrimaryProfile.name = TEST_NAME;
         mPrimaryProfile.id = 10;
-        PreferenceScreen screen = mock(PreferenceScreen.class);
-        mController.displayPreference(screen);
+        mController.displayPreference(mScreen);
 
         final ArgumentCaptor<Preference> argumentCaptor = ArgumentCaptor.forClass(Preference.class);
-        verify(screen).addPreference(argumentCaptor.capture());
+        verify(mScreen).addPreference(argumentCaptor.capture());
         Preference preference = argumentCaptor.getValue();
 
         assertThat(preference.getTitle()).isEqualTo(TEST_NAME);
@@ -85,11 +88,10 @@
     public void tappingProfilePreferenceSendsToStorageProfileFragment() throws Exception {
         mPrimaryProfile.name = TEST_NAME;
         mPrimaryProfile.id = 10;
-        PreferenceScreen screen = mock(PreferenceScreen.class);
-        mController.displayPreference(screen);
+        mController.displayPreference(mScreen);
 
         final ArgumentCaptor<Preference> argumentCaptor = ArgumentCaptor.forClass(Preference.class);
-        verify(screen).addPreference(argumentCaptor.capture());
+        verify(mScreen).addPreference(argumentCaptor.capture());
         Preference preference = argumentCaptor.getValue();
         assertThat(mController.handlePreferenceTreeClick(preference)).isTrue();
         final ArgumentCaptor<Intent> intentCaptor = ArgumentCaptor.forClass(Intent.class);
@@ -105,8 +107,7 @@
     public void acceptingResultUpdatesPreferenceSize() throws Exception {
         mPrimaryProfile.name = TEST_NAME;
         mPrimaryProfile.id = 10;
-        PreferenceScreen screen = mock(PreferenceScreen.class);
-        mController.displayPreference(screen);
+        mController.displayPreference(mScreen);
         SparseArray<StorageAsyncLoader.AppsStorageResult> result = new SparseArray<>();
         StorageAsyncLoader.AppsStorageResult userResult =
                 new StorageAsyncLoader.AppsStorageResult();
@@ -115,7 +116,7 @@
 
         mController.handleResult(result);
         final ArgumentCaptor<Preference> argumentCaptor = ArgumentCaptor.forClass(Preference.class);
-        verify(screen).addPreference(argumentCaptor.capture());
+        verify(mScreen).addPreference(argumentCaptor.capture());
         Preference preference = argumentCaptor.getValue();
 
         assertThat(preference.getSummary()).isEqualTo("99.00B");