diff --git a/res/xml/app_info_settings.xml b/res/xml/app_info_settings.xml
index 664210be1c3..99c76b8936f 100644
--- a/res/xml/app_info_settings.xml
+++ b/res/xml/app_info_settings.xml
@@ -132,6 +132,17 @@
+
+
+
+
+
+
+
mCallbacks = new ArrayList<>();
@@ -180,7 +176,7 @@ public class AppInfoDashboardFragment extends DashboardFragment
@VisibleForTesting
ActionButtonPreference mActionButtons;
- private InstantAppButtonsController mInstantAppButtonsController;
+ private InstantAppButtonsPreferenceController mInstantAppButtonPreferenceController;
/**
* Callback to invoke when app info has been changed.
@@ -335,8 +331,6 @@ public class AppInfoDashboardFragment extends DashboardFragment
}
setHasOptionsMenu(true);
-
- addDynamicPrefs();
}
@Override
@@ -381,6 +375,10 @@ public class AppInfoDashboardFragment extends DashboardFragment
controllers.add(new AppOpenByDefaultPreferenceController(context, this));
controllers.add(new AppPermissionPreferenceController(context, this, packageName));
controllers.add(new AppVersionPreferenceController(context, this));
+ controllers.add(new InstantAppDomainsPreferenceController(context, this));
+ final AppInstallerInfoPreferenceController appInstallerInfoPreferenceController =
+ new AppInstallerInfoPreferenceController(context, this, packageName);
+ controllers.add(appInstallerInfoPreferenceController);
for (AbstractPreferenceController controller : controllers) {
mCallbacks.add((Callback) controller);
@@ -388,6 +386,9 @@ public class AppInfoDashboardFragment extends DashboardFragment
// The following are controllers for preferences that don't need to refresh the preference
// state when app state changes.
+ mInstantAppButtonPreferenceController =
+ new InstantAppButtonsPreferenceController(context, this, packageName);
+ controllers.add(mInstantAppButtonPreferenceController);
controllers.add(new AppBatteryPreferenceController(context, this, packageName, lifecycle));
controllers.add(new AppMemoryPreferenceController(context, this, lifecycle));
controllers.add(new DefaultHomeShortcutPreferenceController(context, packageName));
@@ -407,6 +408,9 @@ public class AppInfoDashboardFragment extends DashboardFragment
controllers.add(new PreferenceCategoryController(
context, KEY_ADVANCED_APP_INFO_CATEGORY, advancedAppInfoControllers));
+ controllers.add(new AppInstallerPreferenceCategoryController(
+ context, Arrays.asList(appInstallerInfoPreferenceController)));
+
return controllers;
}
@@ -444,8 +448,6 @@ public class AppInfoDashboardFragment extends DashboardFragment
.styleActionBar(activity)
.bindHeaderButtons();
- mInstantAppDomainsPreference =
- (AppDomainsPreference) findPreference(KEY_INSTANT_APP_SUPPORTED_LINKS);
}
@Override
@@ -536,24 +538,6 @@ public class AppInfoDashboardFragment extends DashboardFragment
}
}
- /**
- * Utility method to hide and show specific preferences based on whether the app being displayed
- * is an Instant App or an installed app.
- */
- @VisibleForTesting
- void prepareInstantAppPrefs() {
- final boolean isInstant = AppUtils.isInstant(mPackageInfo.applicationInfo);
- if (isInstant) {
- Set handledDomainSet = Utils.getHandledDomains(mPm, mPackageInfo.packageName);
- String[] handledDomains = handledDomainSet.toArray(new String[handledDomainSet.size()]);
- mInstantAppDomainsPreference.setTitles(handledDomains);
- // Dummy values, unused in the implementation
- mInstantAppDomainsPreference.setValues(new int[handledDomains.length]);
- } else {
- getPreferenceScreen().removePreference(mInstantAppDomainsPreference);
- }
- }
-
// Utility method to set application label and icon.
private void setAppLabelAndIcon(PackageInfo pkgInfo) {
final View appSnippet = mHeader.findViewById(R.id.entity_header);
@@ -642,7 +626,6 @@ public class AppInfoDashboardFragment extends DashboardFragment
checkForceStop();
setAppLabelAndIcon(mPackageInfo);
initUninstallButtons();
- prepareInstantAppPrefs();
// Update the preference summaries.
Activity context = getActivity();
@@ -676,7 +659,8 @@ public class AppInfoDashboardFragment extends DashboardFragment
return true;
}
- protected AlertDialog createDialog(int id, int errorCode) {
+ @VisibleForTesting
+ AlertDialog createDialog(int id, int errorCode) {
switch (id) {
case DLG_DISABLE:
return new AlertDialog.Builder(getActivity())
@@ -722,10 +706,7 @@ public class AppInfoDashboardFragment extends DashboardFragment
.setNegativeButton(R.string.dlg_cancel, null)
.create();
}
- if (mInstantAppButtonsController != null) {
- return mInstantAppButtonsController.createDialog(id);
- }
- return null;
+ return mInstantAppButtonPreferenceController.createDialog(id);
}
private void uninstallPkg(String packageName, boolean allUsers, boolean andDisable) {
@@ -870,57 +851,6 @@ public class AppInfoDashboardFragment extends DashboardFragment
|| (mUserManager.isSplitSystemUser() && userCount == 2);
}
- private void addDynamicPrefs() {
- if (UserManager.get(getContext()).isManagedProfile()) {
- return;
- }
- addAppInstallerInfoPref(getPreferenceScreen());
- maybeAddInstantAppButtons();
- }
-
- private void addAppInstallerInfoPref(PreferenceScreen screen) {
- String installerPackageName =
- AppStoreUtil.getInstallerPackageName(getContext(), mPackageName);
-
- final CharSequence installerLabel = Utils.getApplicationLabel(getContext(),
- installerPackageName);
- if (installerLabel == null) {
- return;
- }
- final int detailsStringId = AppUtils.isInstant(mPackageInfo.applicationInfo)
- ? R.string.instant_app_details_summary
- : R.string.app_install_details_summary;
- PreferenceCategory category = new PreferenceCategory(getPrefContext());
- category.setTitle(R.string.app_install_details_group_title);
- screen.addPreference(category);
- Preference pref = new Preference(getPrefContext());
- pref.setTitle(R.string.app_install_details_title);
- pref.setKey("app_info_store");
- pref.setSummary(getString(detailsStringId, installerLabel));
-
- Intent intent =
- AppStoreUtil.getAppStoreLink(getContext(), installerPackageName, mPackageName);
- if (intent != null) {
- pref.setIntent(intent);
- } else {
- pref.setEnabled(false);
- }
- category.addPreference(pref);
- }
-
- @VisibleForTesting
- void maybeAddInstantAppButtons() {
- if (AppUtils.isInstant(mPackageInfo.applicationInfo)) {
- LayoutPreference buttons = (LayoutPreference) findPreference(KEY_INSTANT_APP_BUTTONS);
- mInstantAppButtonsController = mApplicationFeatureProvider
- .newInstantAppButtonsController(this,
- buttons.findViewById(R.id.instant_app_button_container),
- id -> showDialogInner(id, 0))
- .setPackageName(mPackageName)
- .show();
- }
- }
-
private void onPackageRemoved() {
getActivity().finishActivity(SUB_INFO_FRAGMENT);
getActivity().finishAndRemoveTask();
@@ -1041,9 +971,9 @@ public class AppInfoDashboardFragment extends DashboardFragment
mFinishing = true;
}
- private void showDialogInner(int id, int moveErrorCode) {
+ public void showDialogInner(int id, int moveErrorCode) {
DialogFragment newFragment =
- AppInfoBase.MyAlertDialogFragment.newInstance(id, moveErrorCode);
+ MyAlertDialogFragment.newInstance(id, moveErrorCode);
newFragment.setTargetFragment(this, 0);
newFragment.show(getFragmentManager(), "dialog " + id);
}
@@ -1094,8 +1024,8 @@ public class AppInfoDashboardFragment extends DashboardFragment
public static void startAppInfoFragment(Class> fragment, int titleRes,
String pkg, int uid, Activity source, int request, int sourceMetricsCategory) {
Bundle args = new Bundle();
- args.putString(AppInfoBase.ARG_PACKAGE_NAME, pkg);
- args.putInt(AppInfoBase.ARG_PACKAGE_UID, uid);
+ args.putString(ARG_PACKAGE_NAME, pkg);
+ args.putInt(ARG_PACKAGE_UID, uid);
Intent intent = Utils.onBuildStartFragmentIntent(source, fragment.getName(),
args, null, titleRes, null, false, sourceMetricsCategory);
@@ -1116,16 +1046,16 @@ public class AppInfoDashboardFragment extends DashboardFragment
public Dialog onCreateDialog(Bundle savedInstanceState) {
int id = getArguments().getInt(ARG_ID);
int errorCode = getArguments().getInt("moveError");
- Dialog dialog = ((AppInfoBase) getTargetFragment()).createDialog(id, errorCode);
+ Dialog dialog = ((AppInfoDashboardFragment) getTargetFragment())
+ .createDialog(id, errorCode);
if (dialog == null) {
throw new IllegalArgumentException("unknown id " + id);
}
return dialog;
}
- public static AppInfoBase.MyAlertDialogFragment newInstance(int id, int errorCode) {
- AppInfoBase.MyAlertDialogFragment
- dialogFragment = new AppInfoBase.MyAlertDialogFragment();
+ public static MyAlertDialogFragment newInstance(int id, int errorCode) {
+ MyAlertDialogFragment dialogFragment = new MyAlertDialogFragment();
Bundle args = new Bundle();
args.putInt(ARG_ID, id);
args.putInt("moveError", errorCode);
diff --git a/src/com/android/settings/applications/AppStoreUtil.java b/src/com/android/settings/applications/AppStoreUtil.java
index f9b95b0610b..13e551692c6 100644
--- a/src/com/android/settings/applications/AppStoreUtil.java
+++ b/src/com/android/settings/applications/AppStoreUtil.java
@@ -16,11 +16,9 @@
package com.android.settings.applications;
-
import android.content.Context;
import android.content.Intent;
import android.content.pm.ResolveInfo;
-import android.net.Uri;
import android.util.Log;
// This class provides methods that help dealing with app stores.
@@ -43,9 +41,6 @@ public class AppStoreUtil {
} catch (IllegalArgumentException e) {
Log.e(LOG_TAG, "Exception while retrieving the package installer of " + packageName, e);
}
- if (installerPackageName == null) {
- return null;
- }
return installerPackageName;
}
diff --git a/src/com/android/settings/applications/appinfo/AppInstallerInfoPreferenceController.java b/src/com/android/settings/applications/appinfo/AppInstallerInfoPreferenceController.java
new file mode 100644
index 00000000000..2449004b525
--- /dev/null
+++ b/src/com/android/settings/applications/appinfo/AppInstallerInfoPreferenceController.java
@@ -0,0 +1,69 @@
+/*
+ * 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.applications.appinfo;
+
+import android.content.Context;
+import android.content.Intent;
+import android.os.UserManager;
+import android.support.v7.preference.Preference;
+
+import com.android.settings.R;
+import com.android.settings.Utils;
+import com.android.settings.applications.AppInfoDashboardFragment;
+import com.android.settings.applications.AppStoreUtil;
+import com.android.settingslib.applications.AppUtils;
+
+public class AppInstallerInfoPreferenceController extends AppInfoPreferenceControllerBase {
+
+ private static final String KEY_APP_INSTALLER_INFO = "app_info_store";
+
+ private final String mPackageName;
+ private final String mInstallerPackage;
+ private final CharSequence mInstallerLabel;
+
+ public AppInstallerInfoPreferenceController(Context context, AppInfoDashboardFragment parent,
+ String packageName) {
+ super(context, parent, KEY_APP_INSTALLER_INFO);
+ mPackageName = packageName;
+ mInstallerPackage = AppStoreUtil.getInstallerPackageName(mContext, mPackageName);
+ mInstallerLabel = Utils.getApplicationLabel(mContext, mInstallerPackage);
+ }
+
+ @Override
+ public int getAvailabilityStatus() {
+ if (UserManager.get(mContext).isManagedProfile()) {
+ return DISABLED_FOR_USER;
+ }
+ return mInstallerLabel!= null ? AVAILABLE : DISABLED_FOR_USER;
+ }
+
+ @Override
+ public void updateState(Preference preference) {
+ final int detailsStringId = AppUtils.isInstant(mParent.getPackageInfo().applicationInfo)
+ ? R.string.instant_app_details_summary
+ : R.string.app_install_details_summary;
+ preference.setSummary(mContext.getString(detailsStringId, mInstallerLabel));
+
+ Intent intent = AppStoreUtil.getAppStoreLink(mContext, mInstallerPackage, mPackageName);
+ if (intent != null) {
+ preference.setIntent(intent);
+ } else {
+ preference.setEnabled(false);
+ }
+ }
+
+}
diff --git a/src/com/android/settings/applications/appinfo/AppInstallerPreferenceCategoryController.java b/src/com/android/settings/applications/appinfo/AppInstallerPreferenceCategoryController.java
new file mode 100644
index 00000000000..0e6ffe8dcd2
--- /dev/null
+++ b/src/com/android/settings/applications/appinfo/AppInstallerPreferenceCategoryController.java
@@ -0,0 +1,35 @@
+/*
+ * 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.applications.appinfo;
+
+import android.content.Context;
+
+import com.android.settings.widget.PreferenceCategoryController;
+import com.android.settingslib.core.AbstractPreferenceController;
+
+import java.util.List;
+
+public class AppInstallerPreferenceCategoryController extends PreferenceCategoryController {
+
+ private static final String KEY_APP_INSTALLER_INFO_CATEGORY = "app_installer";
+
+ public AppInstallerPreferenceCategoryController(Context context,
+ List childrenControllers) {
+ super(context, KEY_APP_INSTALLER_INFO_CATEGORY, childrenControllers);
+ }
+
+}
diff --git a/src/com/android/settings/applications/appinfo/InstantAppButtonsPreferenceController.java b/src/com/android/settings/applications/appinfo/InstantAppButtonsPreferenceController.java
new file mode 100644
index 00000000000..e35fa76b85f
--- /dev/null
+++ b/src/com/android/settings/applications/appinfo/InstantAppButtonsPreferenceController.java
@@ -0,0 +1,75 @@
+/*
+ * 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.applications.appinfo;
+
+import android.app.AlertDialog;
+import android.content.Context;
+import android.support.annotation.VisibleForTesting;
+import android.support.v7.preference.PreferenceScreen;
+
+import com.android.settings.R;
+import com.android.settings.applications.AppInfoDashboardFragment;
+import com.android.settings.applications.ApplicationFeatureProvider;
+import com.android.settings.applications.LayoutPreference;
+import com.android.settings.applications.instantapps.InstantAppButtonsController;
+import com.android.settings.core.BasePreferenceController;
+import com.android.settings.overlay.FeatureFactory;
+import com.android.settingslib.applications.AppUtils;
+
+public class InstantAppButtonsPreferenceController extends BasePreferenceController {
+
+ private static final String KEY_INSTANT_APP_BUTTONS = "instant_app_buttons";
+
+ private final AppInfoDashboardFragment mParent;
+ private final String mPackageName;
+ private InstantAppButtonsController mInstantAppButtonsController;
+
+ public InstantAppButtonsPreferenceController(Context context, AppInfoDashboardFragment parent,
+ String packageName) {
+ super(context, KEY_INSTANT_APP_BUTTONS);
+ mParent = parent;
+ mPackageName = packageName;
+ }
+
+ @Override
+ public int getAvailabilityStatus() {
+ return AppUtils.isInstant(mParent.getPackageInfo().applicationInfo)
+ ? AVAILABLE : DISABLED_FOR_USER;
+ }
+
+ @Override
+ public void displayPreference(PreferenceScreen screen) {
+ super.displayPreference(screen);
+ LayoutPreference buttons =
+ (LayoutPreference) screen.findPreference(KEY_INSTANT_APP_BUTTONS);
+ mInstantAppButtonsController = getApplicationFeatureProvider()
+ .newInstantAppButtonsController(mParent,
+ buttons.findViewById(R.id.instant_app_button_container),
+ id -> mParent.showDialogInner(id, 0))
+ .setPackageName(mPackageName)
+ .show();
+ }
+
+ public AlertDialog createDialog(int id) {
+ return mInstantAppButtonsController.createDialog(id);
+ }
+
+ @VisibleForTesting
+ ApplicationFeatureProvider getApplicationFeatureProvider() {
+ return FeatureFactory.getFactory(mContext).getApplicationFeatureProvider(mContext);
+ }
+}
diff --git a/src/com/android/settings/applications/appinfo/InstantAppDomainsPreferenceController.java b/src/com/android/settings/applications/appinfo/InstantAppDomainsPreferenceController.java
new file mode 100644
index 00000000000..1d2229127da
--- /dev/null
+++ b/src/com/android/settings/applications/appinfo/InstantAppDomainsPreferenceController.java
@@ -0,0 +1,60 @@
+/*
+ * 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.applications.appinfo;
+
+import android.content.Context;
+import android.content.pm.PackageManager;
+import android.support.v7.preference.Preference;
+
+import com.android.settings.Utils;
+import com.android.settings.applications.AppDomainsPreference;
+import com.android.settings.applications.AppInfoDashboardFragment;
+import com.android.settingslib.applications.AppUtils;
+
+import java.util.Set;
+
+public class InstantAppDomainsPreferenceController extends AppInfoPreferenceControllerBase {
+
+ private static final String KEY_INSTANT_APP_SUPPORTED_LINKS =
+ "instant_app_launch_supported_domain_urls";
+
+ private PackageManager mPackageManager;
+
+ public InstantAppDomainsPreferenceController(Context context, AppInfoDashboardFragment parent) {
+ super(context, parent, KEY_INSTANT_APP_SUPPORTED_LINKS);
+ mPackageManager = mContext.getPackageManager();
+ }
+
+ @Override
+ public int getAvailabilityStatus() {
+ return AppUtils.isInstant(mParent.getPackageInfo().applicationInfo)
+ ? AVAILABLE : DISABLED_FOR_USER;
+ }
+
+ @Override
+ public void updateState(Preference preference) {
+ final AppDomainsPreference instantAppDomainsPreference = (AppDomainsPreference) preference;
+ final Set handledDomainSet =
+ Utils.getHandledDomains(mPackageManager, mParent.getPackageInfo().packageName);
+ final String[] handledDomains =
+ handledDomainSet.toArray(new String[handledDomainSet.size()]);
+ instantAppDomainsPreference.setTitles(handledDomains);
+ // Dummy values, unused in the implementation
+ instantAppDomainsPreference.setValues(new int[handledDomains.length]);
+ }
+
+}
diff --git a/src/com/android/settings/applications/instantapps/InstantAppButtonsController.java b/src/com/android/settings/applications/instantapps/InstantAppButtonsController.java
index 28e612c98ff..42474a8b297 100644
--- a/src/com/android/settings/applications/instantapps/InstantAppButtonsController.java
+++ b/src/com/android/settings/applications/instantapps/InstantAppButtonsController.java
@@ -21,7 +21,6 @@ import android.app.Fragment;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
-import android.content.pm.PackageManager;
import android.os.UserHandle;
import android.view.View;
import android.widget.Button;
diff --git a/tests/robotests/src/com/android/settings/applications/AppInfoDashboardFragmentTest.java b/tests/robotests/src/com/android/settings/applications/AppInfoDashboardFragmentTest.java
index d710d7c1953..e742549e720 100644
--- a/tests/robotests/src/com/android/settings/applications/AppInfoDashboardFragmentTest.java
+++ b/tests/robotests/src/com/android/settings/applications/AppInfoDashboardFragmentTest.java
@@ -23,13 +23,10 @@ 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.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
-import android.app.AlertDialog;
import android.app.AppOpsManager;
-import android.app.Fragment;
import android.content.Context;
import android.content.Intent;
import android.content.pm.ApplicationInfo;
@@ -37,16 +34,10 @@ import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.res.Resources;
import android.os.UserManager;
-import android.support.v7.preference.Preference;
-import android.support.v7.preference.PreferenceManager;
-import android.support.v7.preference.PreferenceScreen;
-import android.view.View;
import com.android.settings.R;
import com.android.settings.SettingsActivity;
import com.android.settings.TestConfig;
-import com.android.settings.applications.instantapps.InstantAppButtonsController;
-import com.android.settings.applications.instantapps.InstantAppButtonsController.ShowDialogDelegate;
import com.android.settings.testutils.FakeFeatureFactory;
import com.android.settings.testutils.SettingsRobolectricTestRunner;
import com.android.settings.widget.ActionButtonPreferenceTest;
@@ -246,101 +237,6 @@ public final class AppInfoDashboardFragmentTest {
verify(mAppDetail.mActionButtons).setButton2Visible(false);
}
- @Test
- public void instantApps_buttonControllerHandlesDialog() {
- InstantAppButtonsController mockController = mock(InstantAppButtonsController.class);
- ReflectionHelpers.setField(
- mAppDetail, "mInstantAppButtonsController", mockController);
- // Make sure first that button controller is not called for supported dialog id
- AlertDialog mockDialog = mock(AlertDialog.class);
- when(mockController.createDialog(InstantAppButtonsController.DLG_CLEAR_APP))
- .thenReturn(mockDialog);
- assertThat(mAppDetail.createDialog(InstantAppButtonsController.DLG_CLEAR_APP, 0))
- .isEqualTo(mockDialog);
- verify(mockController).createDialog(InstantAppButtonsController.DLG_CLEAR_APP);
- }
-
- // A helper class for testing the InstantAppButtonsController - it lets us look up the
- // preference associated with a key for instant app buttons and get back a mock
- // LayoutPreference (to avoid a null pointer exception).
- public static class InstalledAppDetailsWithMockInstantButtons extends InstalledAppDetails {
- @Mock
- private LayoutPreference mInstantButtons;
-
- public InstalledAppDetailsWithMockInstantButtons() {
- super();
- MockitoAnnotations.initMocks(this);
- }
-
- @Override
- public Preference findPreference(CharSequence key) {
- if (key == "instant_app_buttons") {
- return mInstantButtons;
- }
- return super.findPreference(key);
- }
- }
-
- @Test
- public void instantApps_instantSpecificButtons() {
- // Make this app appear to be instant.
- ReflectionHelpers.setStaticField(AppUtils.class, "sInstantAppDataProvider",
- (InstantAppDataProvider) (i -> true));
- final PackageInfo packageInfo = mock(PackageInfo.class);
-
- final InstalledAppDetailsWithMockInstantButtons
- fragment = new InstalledAppDetailsWithMockInstantButtons();
- ReflectionHelpers.setField(fragment, "mPackageInfo", packageInfo);
- ReflectionHelpers.setField(fragment, "mApplicationFeatureProvider",
- mFeatureFactory.applicationFeatureProvider);
-
- final InstantAppButtonsController buttonsController =
- mock(InstantAppButtonsController.class);
- when(buttonsController.setPackageName(nullable(String.class)))
- .thenReturn(buttonsController);
- when(mFeatureFactory.applicationFeatureProvider.newInstantAppButtonsController(
- nullable(Fragment.class), nullable(View.class), nullable(ShowDialogDelegate.class)))
- .thenReturn(buttonsController);
-
- fragment.maybeAddInstantAppButtons();
- verify(buttonsController).setPackageName(nullable(String.class));
- verify(buttonsController).show();
- }
-
- @Test
- public void instantApps_removeCorrectPref() {
- PreferenceScreen mockPreferenceScreen = mock(PreferenceScreen.class);
- PreferenceManager mockPreferenceManager = mock(PreferenceManager.class);
- AppDomainsPreference mockAppDomainsPref = mock(AppDomainsPreference.class);
- PackageInfo mockPackageInfo = mock(PackageInfo.class);
- PackageManager mockPackageManager = mock(PackageManager.class);
- ReflectionHelpers.setField(
- mAppDetail, "mInstantAppDomainsPreference", mockAppDomainsPref);
- ReflectionHelpers.setField(
- mAppDetail, "mPreferenceManager", mockPreferenceManager);
- ReflectionHelpers.setField(
- mAppDetail, "mPackageInfo", mockPackageInfo);
- ReflectionHelpers.setField(
- mAppDetail, "mPm", mockPackageManager);
- when(mockPreferenceManager.getPreferenceScreen()).thenReturn(mockPreferenceScreen);
-
- ReflectionHelpers.setStaticField(AppUtils.class, "sInstantAppDataProvider",
- (InstantAppDataProvider) (i -> false));
- mAppDetail.prepareInstantAppPrefs();
-
- // For the non instant case we remove the app domain pref, and leave the launch pref
- verify(mockPreferenceScreen).removePreference(mockAppDomainsPref);
-
- // For the instant app case we remove the launch preff, and leave the app domain pref
- ReflectionHelpers.setStaticField(AppUtils.class, "sInstantAppDataProvider",
- (InstantAppDataProvider) (i -> true));
-
- mAppDetail.prepareInstantAppPrefs();
- // Will be 1 still due to above call
- verify(mockPreferenceScreen, times(1))
- .removePreference(mockAppDomainsPref);
- }
-
@Test
public void onActivityResult_uninstalledUpdates_shouldInvalidateOptionsMenu() {
doReturn(true).when(mAppDetail).refreshUi();
diff --git a/tests/robotests/src/com/android/settings/applications/appinfo/AppInstallerInfoPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/applications/appinfo/AppInstallerInfoPreferenceControllerTest.java
new file mode 100644
index 00000000000..ffbc8f55954
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/applications/appinfo/AppInstallerInfoPreferenceControllerTest.java
@@ -0,0 +1,147 @@
+/*
+ * 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.applications.appinfo;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.ArgumentMatchers.anyString;
+import static org.mockito.Mockito.any;
+import static org.mockito.Mockito.eq;
+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 static org.mockito.Mockito.when;
+
+import android.content.Context;
+import android.content.Intent;
+import android.content.pm.ActivityInfo;
+import android.content.pm.ApplicationInfo;
+import android.content.pm.PackageInfo;
+import android.content.pm.PackageManager;
+import android.content.pm.ResolveInfo;
+import android.os.UserManager;
+import android.support.v7.preference.Preference;
+
+import com.android.settings.TestConfig;
+import com.android.settings.applications.AppInfoDashboardFragment;
+import com.android.settings.testutils.SettingsRobolectricTestRunner;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.robolectric.RuntimeEnvironment;
+import org.robolectric.annotation.Config;
+
+@RunWith(SettingsRobolectricTestRunner.class)
+@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
+public class AppInstallerInfoPreferenceControllerTest {
+
+ @Mock
+ private UserManager mUserManager;
+ @Mock
+ private PackageManager mPackageManager;
+ @Mock
+ private ApplicationInfo mAppInfo;
+ @Mock
+ private AppInfoDashboardFragment mFragment;
+ @Mock
+ private Preference mPreference;
+
+ private Context mContext;
+ private AppInstallerInfoPreferenceController mController;
+
+ @Before
+ public void setUp() throws PackageManager.NameNotFoundException {
+ MockitoAnnotations.initMocks(this);
+ mContext = spy(RuntimeEnvironment.application);
+ when(mContext.getSystemService(Context.USER_SERVICE)).thenReturn(mUserManager);
+ when(mContext.getPackageManager()).thenReturn(mPackageManager);
+ final String installerPackage = "Installer1";
+ when(mPackageManager.getInstallerPackageName(anyString())).thenReturn(installerPackage);
+ when(mPackageManager.getApplicationInfo(eq(installerPackage), anyInt()))
+ .thenReturn(mAppInfo);
+ mController = new AppInstallerInfoPreferenceController(mContext, mFragment, "Package1");
+ }
+
+ @Test
+ public void getAvailabilityStatus_managedProfile_shouldReturnDisabled() {
+ when(mUserManager.isManagedProfile()).thenReturn(true);
+
+ assertThat(mController.getAvailabilityStatus()).isEqualTo(mController.DISABLED_FOR_USER);
+ }
+
+ @Test
+ public void getAvailabilityStatus_noAppLabel_shouldReturnDisabled() {
+ when(mUserManager.isManagedProfile()).thenReturn(false);
+
+ assertThat(mController.getAvailabilityStatus()).isEqualTo(mController.DISABLED_FOR_USER);
+ }
+
+ @Test
+ public void getAvailabilityStatus_hasAppLabel_shouldReturnAvailable() {
+ when(mUserManager.isManagedProfile()).thenReturn(false);
+ when(mAppInfo.loadLabel(mPackageManager)).thenReturn("Label1");
+ mController = new AppInstallerInfoPreferenceController(mContext, mFragment, "Package1");
+
+ assertThat(mController.getAvailabilityStatus()).isEqualTo(mController.AVAILABLE);
+ }
+
+ @Test
+ public void updateState_shouldSetSummary() {
+ final PackageInfo packageInfo = mock(PackageInfo.class);
+ packageInfo.applicationInfo = mAppInfo;
+ when(mFragment.getPackageInfo()).thenReturn(packageInfo);
+
+ mController.updateState(mPreference);
+
+ verify(mPreference).setSummary(any());
+ }
+
+ @Test
+ public void updateState_noAppStoreLink_shouldDisablePreference() {
+ final PackageInfo packageInfo = mock(PackageInfo.class);
+ packageInfo.applicationInfo = mAppInfo;
+ when(mFragment.getPackageInfo()).thenReturn(packageInfo);
+ when(mPackageManager.resolveActivity(any(), anyInt())).thenReturn(null);
+
+ mController.updateState(mPreference);
+
+ verify(mPreference).setEnabled(false);
+ }
+
+ @Test
+ public void updateState_hasAppStoreLink_shouldSetPreferenceIntent() {
+ final PackageInfo packageInfo = mock(PackageInfo.class);
+ packageInfo.applicationInfo = mAppInfo;
+ when(mFragment.getPackageInfo()).thenReturn(packageInfo);
+ final ResolveInfo resolveInfo = new ResolveInfo();
+ resolveInfo.activityInfo = new ActivityInfo();
+ resolveInfo.activityInfo.packageName = "Pkg1";
+ resolveInfo.activityInfo.name = "Name1";
+ when(mPackageManager.resolveActivity(any(), anyInt())).thenReturn(resolveInfo);
+
+ mController.updateState(mPreference);
+
+ verify(mPreference, never()).setEnabled(false);
+ verify(mPreference).setIntent(any(Intent.class));
+ }
+
+}
diff --git a/tests/robotests/src/com/android/settings/applications/appinfo/InstantAppButtonsPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/applications/appinfo/InstantAppButtonsPreferenceControllerTest.java
new file mode 100644
index 00000000000..121659538a4
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/applications/appinfo/InstantAppButtonsPreferenceControllerTest.java
@@ -0,0 +1,133 @@
+/*
+ * 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.applications.appinfo;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.ArgumentMatchers.nullable;
+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.app.AlertDialog;
+import android.app.Fragment;
+import android.content.Context;
+import android.content.pm.ApplicationInfo;
+import android.content.pm.PackageInfo;
+import android.content.pm.PackageManager;
+import android.support.v7.preference.PreferenceScreen;
+import android.view.View;
+
+import com.android.settings.TestConfig;
+import com.android.settings.applications.AppInfoDashboardFragment;
+import com.android.settings.applications.LayoutPreference;
+import com.android.settings.applications.instantapps.InstantAppButtonsController;
+import com.android.settings.testutils.FakeFeatureFactory;
+import com.android.settings.testutils.SettingsRobolectricTestRunner;
+import com.android.settingslib.applications.AppUtils;
+import com.android.settingslib.applications.instantapps.InstantAppDataProvider;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.robolectric.RuntimeEnvironment;
+import org.robolectric.annotation.Config;
+import org.robolectric.util.ReflectionHelpers;
+
+@RunWith(SettingsRobolectricTestRunner.class)
+@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
+public class InstantAppButtonsPreferenceControllerTest {
+
+ @Mock
+ private PackageManager mPackageManager;
+ @Mock
+ private ApplicationInfo mAppInfo;
+ @Mock
+ private AppInfoDashboardFragment mFragment;
+
+ private Context mContext;
+ private InstantAppButtonsPreferenceController mController;
+ private FakeFeatureFactory mFeatureFactory;
+
+ @Before
+ public void setUp() throws PackageManager.NameNotFoundException {
+ MockitoAnnotations.initMocks(this);
+ mFeatureFactory = FakeFeatureFactory.setupForTest();
+ mContext = spy(RuntimeEnvironment.application);
+ final PackageInfo packageInfo = mock(PackageInfo.class);
+ packageInfo.applicationInfo = mAppInfo;
+ when(mFragment.getPackageInfo()).thenReturn(packageInfo);
+ mController =
+ spy(new InstantAppButtonsPreferenceController(mContext, mFragment, "Package1"));
+ }
+
+ @Test
+ public void getAvailabilityStatus_notInstantApp_shouldReturnDisabled() {
+ ReflectionHelpers.setStaticField(AppUtils.class, "sInstantAppDataProvider",
+ (InstantAppDataProvider) (i -> false));
+
+ assertThat(mController.getAvailabilityStatus()).isEqualTo(mController.DISABLED_FOR_USER);
+ }
+
+ @Test
+ public void getAvailabilityStatus_isInstantApp_shouldReturnAvailable() {
+ ReflectionHelpers.setStaticField(AppUtils.class, "sInstantAppDataProvider",
+ (InstantAppDataProvider) (i -> true));
+
+ assertThat(mController.getAvailabilityStatus()).isEqualTo(mController.AVAILABLE);
+ }
+
+ @Test
+ public void displayPreference_shouldSetPreferenceTitle() {
+ final PreferenceScreen screen = mock(PreferenceScreen.class);
+ final LayoutPreference preference = mock(LayoutPreference.class);
+ when(screen.findPreference(mController.getPreferenceKey())).thenReturn(preference);
+ when(mController.getApplicationFeatureProvider())
+ .thenReturn(mFeatureFactory.applicationFeatureProvider);
+ final InstantAppButtonsController buttonsController =
+ mock(InstantAppButtonsController.class);
+ when(buttonsController.setPackageName(nullable(String.class)))
+ .thenReturn(buttonsController);
+ when(mFeatureFactory.applicationFeatureProvider.newInstantAppButtonsController(
+ nullable(Fragment.class), nullable(View.class),
+ nullable(InstantAppButtonsController.ShowDialogDelegate.class)))
+ .thenReturn(buttonsController);
+
+ mController.displayPreference(screen);
+
+ verify(buttonsController).setPackageName(nullable(String.class));
+ verify(buttonsController).show();
+ }
+
+ @Test
+ public void createDialog_shouldReturnDialogFromButtonController() {
+ final InstantAppButtonsController buttonsController =
+ mock(InstantAppButtonsController.class);
+ ReflectionHelpers.setField(
+ mController, "mInstantAppButtonsController", buttonsController);
+ final AlertDialog mockDialog = mock(AlertDialog.class);
+ when(buttonsController.createDialog(InstantAppButtonsController.DLG_CLEAR_APP))
+ .thenReturn(mockDialog);
+
+ assertThat(mController.createDialog(InstantAppButtonsController.DLG_CLEAR_APP))
+ .isEqualTo(mockDialog);
+ }
+
+}
diff --git a/tests/robotests/src/com/android/settings/applications/appinfo/InstantAppDomainsPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/applications/appinfo/InstantAppDomainsPreferenceControllerTest.java
new file mode 100644
index 00000000000..f1776e88e7d
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/applications/appinfo/InstantAppDomainsPreferenceControllerTest.java
@@ -0,0 +1,115 @@
+/*
+ * 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.applications.appinfo;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.Mockito.eq;
+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.pm.ApplicationInfo;
+import android.content.pm.IntentFilterVerificationInfo;
+import android.content.pm.PackageInfo;
+import android.content.pm.PackageManager;
+import android.util.ArraySet;
+
+import com.android.settings.TestConfig;
+import com.android.settings.applications.AppDomainsPreference;
+import com.android.settings.applications.AppInfoDashboardFragment;
+import com.android.settings.testutils.SettingsRobolectricTestRunner;
+import com.android.settingslib.applications.AppUtils;
+import com.android.settingslib.applications.instantapps.InstantAppDataProvider;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.robolectric.RuntimeEnvironment;
+import org.robolectric.annotation.Config;
+import org.robolectric.util.ReflectionHelpers;
+
+import java.util.ArrayList;
+import java.util.List;
+
+@RunWith(SettingsRobolectricTestRunner.class)
+@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
+public class InstantAppDomainsPreferenceControllerTest {
+
+ @Mock
+ private PackageManager mPackageManager;
+ @Mock
+ private ApplicationInfo mAppInfo;
+ @Mock
+ private AppInfoDashboardFragment mFragment;
+ @Mock
+ private AppDomainsPreference mPreference;
+
+ private Context mContext;
+ private InstantAppDomainsPreferenceController mController;
+
+ @Before
+ public void setUp() throws PackageManager.NameNotFoundException {
+ MockitoAnnotations.initMocks(this);
+ mContext = spy(RuntimeEnvironment.application);
+ when(mContext.getPackageManager()).thenReturn(mPackageManager);
+ final PackageInfo packageInfo = mock(PackageInfo.class);
+ packageInfo.applicationInfo = mAppInfo;
+ packageInfo.packageName = "Package1";
+ when(mFragment.getPackageInfo()).thenReturn(packageInfo);
+ mController = new InstantAppDomainsPreferenceController(mContext, mFragment);
+ }
+
+ @Test
+ public void getAvailabilityStatus_notInstantApp_shouldReturnDisabled() {
+ ReflectionHelpers.setStaticField(AppUtils.class, "sInstantAppDataProvider",
+ (InstantAppDataProvider) (i -> false));
+
+ assertThat(mController.getAvailabilityStatus()).isEqualTo(mController.DISABLED_FOR_USER);
+ }
+
+ @Test
+ public void getAvailabilityStatus_isInstantApp_shouldReturnAvailable() {
+ ReflectionHelpers.setStaticField(AppUtils.class, "sInstantAppDataProvider",
+ (InstantAppDataProvider) (i -> true));
+
+ assertThat(mController.getAvailabilityStatus()).isEqualTo(mController.AVAILABLE);
+ }
+
+ @Test
+ public void updateState_shouldSetPreferenceTitle() {
+ final String[] domain = { "Domain1" };
+ final ArraySet domains = new ArraySet<>();
+ domains.add(domain[0]);
+ final List infoList = new ArrayList<>();
+ final IntentFilterVerificationInfo info =
+ new IntentFilterVerificationInfo("Package1", domains);
+ infoList.add(info);
+
+ when(mPackageManager.getIntentFilterVerifications("Package1")).thenReturn(infoList);
+
+ mController.updateState(mPreference);
+
+ verify(mPreference).setTitles(domain);
+ }
+
+}