diff --git a/res/layout/app_action_buttons.xml b/res/layout/app_action_buttons.xml
new file mode 100644
index 00000000000..5b0020549a3
--- /dev/null
+++ b/res/layout/app_action_buttons.xml
@@ -0,0 +1,46 @@
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/res/layout/app_details.xml b/res/layout/app_details.xml
new file mode 100644
index 00000000000..68cc57d6649
--- /dev/null
+++ b/res/layout/app_details.xml
@@ -0,0 +1,91 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/res/values/styles.xml b/res/values/styles.xml
index 0f957a8b1a7..9dab0131cab 100644
--- a/res/values/styles.xml
+++ b/res/values/styles.xml
@@ -452,4 +452,22 @@
- @drawable/ring_progress
+
+
+
+
+
+
+
+
diff --git a/res/xml/installed_app_details_ia.xml b/res/xml/installed_app_details_ia.xml
new file mode 100644
index 00000000000..f4603ed3653
--- /dev/null
+++ b/res/xml/installed_app_details_ia.xml
@@ -0,0 +1,61 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/com/android/settings/applications/AppHeaderController.java b/src/com/android/settings/applications/AppHeaderController.java
new file mode 100644
index 00000000000..f4d87a0fed9
--- /dev/null
+++ b/src/com/android/settings/applications/AppHeaderController.java
@@ -0,0 +1,163 @@
+/*
+ * Copyright (C) 2016 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;
+
+import android.app.Fragment;
+import android.content.Context;
+import android.content.Intent;
+import android.content.pm.PackageInfo;
+import android.content.pm.ResolveInfo;
+import android.content.res.Resources;
+import android.support.annotation.IntDef;
+import android.text.TextUtils;
+import android.util.Log;
+import android.view.View;
+import android.widget.ImageButton;
+import android.widget.ImageView;
+import android.widget.TextView;
+
+import com.android.settings.R;
+import com.android.settings.Utils;
+import com.android.settingslib.applications.ApplicationsState;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
+public class AppHeaderController {
+
+ @IntDef({ActionType.ACTION_APP_INFO,
+ ActionType.ACTION_APP_PREFERENCE,
+ ActionType.ACTION_STORE_DEEP_LINK,
+ ActionType.ACTION_NOTIF_PREFERENCE})
+ @Retention(RetentionPolicy.SOURCE)
+ @interface ActionType {
+ int ACTION_APP_INFO = 0;
+ int ACTION_STORE_DEEP_LINK = 1;
+ int ACTION_APP_PREFERENCE = 2;
+ int ACTION_NOTIF_PREFERENCE = 3;
+ }
+
+ private static final String TAG = "AppDetailFeature";
+
+ private final Context mContext;
+
+ public AppHeaderController(Context context) {
+ mContext = context;
+ }
+
+ public void bindAppHeader(View appSnippet, PackageInfo packageInfo,
+ ApplicationsState.AppEntry appEntry) {
+ final String versionName = packageInfo == null ? null : packageInfo.versionName;
+ final Resources res = appSnippet.getResources();
+
+ // Set Icon
+ final ImageView iconView = (ImageView) appSnippet.findViewById(android.R.id.icon);
+ if (appEntry.icon != null) {
+ iconView.setImageDrawable(appEntry.icon.getConstantState().newDrawable(res));
+ }
+
+ // Set application name.
+ final TextView labelView = (TextView) appSnippet.findViewById(android.R.id.title);
+ labelView.setText(appEntry.label);
+
+ // Version number of application
+ final TextView appVersion = (TextView) appSnippet.findViewById(android.R.id.summary);
+
+ if (!TextUtils.isEmpty(versionName)) {
+ appVersion.setSelected(true);
+ appVersion.setVisibility(View.VISIBLE);
+ appVersion.setText(res.getString(R.string.version_text, String.valueOf(versionName)));
+ } else {
+ appVersion.setVisibility(View.INVISIBLE);
+ }
+ }
+
+ public void bindAppHeaderButtons(Fragment fragment, View appLinkButtons, String packageName,
+ @ActionType int leftAction, @ActionType int rightAction) {
+ ImageButton leftButton = (ImageButton) appLinkButtons.findViewById(R.id.left_button);
+ ImageButton rightButton = (ImageButton) appLinkButtons.findViewById(R.id.right_button);
+
+ bindAppDetailButton(fragment, packageName, leftButton, leftAction);
+ bindAppDetailButton(fragment, packageName, rightButton, rightAction);
+ }
+
+ private void bindAppDetailButton(Fragment fragment, String packageName,
+ ImageButton button, @ActionType int action) {
+ if (button == null) {
+ return;
+ }
+ switch (action) {
+ case ActionType.ACTION_APP_INFO: {
+ if (packageName == null || packageName.equals(Utils.OS_PKG)) {
+ button.setVisibility(View.GONE);
+ } else {
+ // TODO
+ button.setImageResource(com.android.settings.R.drawable.ic_info);
+ button.setVisibility(View.VISIBLE);
+ }
+ return;
+ }
+ case ActionType.ACTION_STORE_DEEP_LINK: {
+ final Intent intent = new Intent(Intent.ACTION_SHOW_APP_INFO)
+ .setPackage(getInstallerPackageName(mContext, packageName));
+ final Intent result = resolveIntent(intent);
+ if (result == null) {
+ button.setVisibility(View.GONE);
+ } else {
+ result.putExtra(Intent.EXTRA_PACKAGE_NAME, packageName);
+ button.setImageResource(R.drawable.ic_sim_sd);
+ button.setOnClickListener(v -> fragment.startActivity(intent));
+ button.setVisibility(View.VISIBLE);
+ }
+ return;
+ }
+ case ActionType.ACTION_NOTIF_PREFERENCE: {
+ // TODO
+ return;
+ }
+ case ActionType.ACTION_APP_PREFERENCE: {
+ final Intent intent = resolveIntent(
+ new Intent(Intent.ACTION_APPLICATION_PREFERENCES).setPackage(packageName));
+ if (intent == null) {
+ button.setVisibility(View.GONE);
+ return;
+ }
+ button.setOnClickListener(v -> fragment.startActivity(intent));
+ button.setVisibility(View.VISIBLE);
+ return;
+ }
+ }
+ }
+
+ private String getInstallerPackageName(Context context, String packageName) {
+ try {
+ return context.getPackageManager().getInstallerPackageName(packageName);
+ } catch (IllegalArgumentException e) {
+ Log.e(TAG, "Exception while retrieving the package installer of " + packageName, e);
+ return null;
+ }
+ }
+
+ private Intent resolveIntent(Intent i) {
+ ResolveInfo result = mContext.getPackageManager().resolveActivity(i, 0);
+ if (result != null) {
+ return new Intent(i.getAction())
+ .setClassName(result.activityInfo.packageName, result.activityInfo.name);
+ }
+ return null;
+ }
+}
diff --git a/src/com/android/settings/applications/ApplicationFeatureProvider.java b/src/com/android/settings/applications/ApplicationFeatureProvider.java
new file mode 100644
index 00000000000..710f02f0b7e
--- /dev/null
+++ b/src/com/android/settings/applications/ApplicationFeatureProvider.java
@@ -0,0 +1,23 @@
+/*
+ * Copyright (C) 2016 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;
+
+public interface ApplicationFeatureProvider {
+
+ AppHeaderController getAppHeaderController();
+}
+
diff --git a/src/com/android/settings/applications/ApplicationFeatureProviderImpl.java b/src/com/android/settings/applications/ApplicationFeatureProviderImpl.java
new file mode 100644
index 00000000000..3223a91cccd
--- /dev/null
+++ b/src/com/android/settings/applications/ApplicationFeatureProviderImpl.java
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2016 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;
+
+import android.content.Context;
+
+public class ApplicationFeatureProviderImpl implements ApplicationFeatureProvider {
+
+ private final Context mContext;
+
+ private AppHeaderController mAppHeaderController;
+
+ public ApplicationFeatureProviderImpl(Context context) {
+ mContext = context.getApplicationContext();
+ }
+
+ @Override
+ public AppHeaderController getAppHeaderController() {
+ if (mAppHeaderController == null) {
+ mAppHeaderController = new AppHeaderController(mContext);
+ }
+ return mAppHeaderController;
+ }
+}
diff --git a/src/com/android/settings/applications/InstalledAppDetails.java b/src/com/android/settings/applications/InstalledAppDetails.java
index 38d4f4992e1..6ffc4c79ff5 100755
--- a/src/com/android/settings/applications/InstalledAppDetails.java
+++ b/src/com/android/settings/applications/InstalledAppDetails.java
@@ -84,6 +84,7 @@ import com.android.settings.SettingsActivity;
import com.android.settings.SettingsPreferenceFragment;
import com.android.settings.Utils;
import com.android.settings.applications.PermissionsSummaryHelper.PermissionsResultCallback;
+import com.android.settings.dashboard.DashboardFeatureProvider;
import com.android.settings.datausage.AppDataUsage;
import com.android.settings.datausage.DataUsageList;
import com.android.settings.datausage.DataUsageSummary;
@@ -92,6 +93,7 @@ import com.android.settings.fuelgauge.PowerUsageDetail;
import com.android.settings.notification.AppNotificationSettings;
import com.android.settings.notification.NotificationBackend;
import com.android.settings.notification.NotificationBackend.AppRow;
+import com.android.settings.overlay.FeatureFactory;
import com.android.settingslib.AppItem;
import com.android.settingslib.RestrictedLockUtils;
import com.android.settingslib.applications.AppUtils;
@@ -138,6 +140,7 @@ public class InstalledAppDetails extends AppInfoBase
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_NOTIFICATION = "notification_settings";
private static final String KEY_STORAGE = "storage_settings";
private static final String KEY_PERMISSION = "permission_settings";
@@ -148,11 +151,15 @@ public class InstalledAppDetails extends AppInfoBase
private static final String NOTIFICATION_TUNER_SETTING = "show_importance_slider";
- private final HashSet mHomePackages = new HashSet();
+ private final HashSet mHomePackages = new HashSet<>();
+
+ private DashboardFeatureProvider mDashboardFeatureProvider;
+ private AppHeaderController mAppHeaderController;
private boolean mInitialized;
private boolean mShowUninstalled;
private LayoutPreference mHeader;
+ private LayoutPreference mFooter;
private Button mUninstallButton;
private boolean mUpdatedSysApp = false;
private Button mForceStopButton;
@@ -164,6 +171,7 @@ public class InstalledAppDetails extends AppInfoBase
private Preference mMemoryPreference;
private boolean mDisableAfterUninstall;
+
// Used for updating notification preference.
private final NotificationBackend mBackend = new NotificationBackend();
@@ -306,9 +314,16 @@ public class InstalledAppDetails extends AppInfoBase
@Override
public void onCreate(Bundle icicle) {
super.onCreate(icicle);
+ final Activity activity = getActivity();
+ mDashboardFeatureProvider =
+ FeatureFactory.getFactory(activity).getDashboardFeatureProvider(activity);
+ mAppHeaderController = FeatureFactory.getFactory(activity)
+ .getApplicationFeatureProvider(activity).getAppHeaderController();
setHasOptionsMenu(true);
- addPreferencesFromResource(R.xml.installed_app_details);
+ addPreferencesFromResource(mDashboardFeatureProvider.isEnabled()
+ ? R.xml.installed_app_details_ia
+ : R.xml.installed_app_details);
addDynamicPrefs();
if (Utils.isBandwidthControlEnabled()) {
@@ -366,7 +381,18 @@ public class InstalledAppDetails extends AppInfoBase
if (mFinishing) {
return;
}
- handleHeader();
+ if (!mDashboardFeatureProvider.isEnabled()) {
+ handleHeader();
+ } else {
+ mHeader = (LayoutPreference) findPreference(KEY_HEADER);
+ mAppHeaderController.bindAppHeaderButtons(
+ this,
+ mHeader.findViewById(R.id.app_detail_links),
+ mPackageName,
+ AppHeaderController.ActionType.ACTION_STORE_DEEP_LINK,
+ AppHeaderController.ActionType.ACTION_APP_PREFERENCE);
+ prepareUninstallAndStop();
+ }
mNotificationPreference = findPreference(KEY_NOTIFICATION);
mNotificationPreference.setOnPreferenceClickListener(this);
@@ -404,7 +430,6 @@ public class InstalledAppDetails extends AppInfoBase
private void handleHeader() {
mHeader = (LayoutPreference) findPreference(KEY_HEADER);
-
// Get Control button panel
View btnPanel = mHeader.findViewById(R.id.control_buttons_panel);
mForceStopButton = (Button) btnPanel.findViewById(R.id.right_button);
@@ -429,6 +454,13 @@ public class InstalledAppDetails extends AppInfoBase
}
}
+ private void prepareUninstallAndStop() {
+ mForceStopButton = (Button) mFooter.findViewById(R.id.right_button);
+ mForceStopButton.setText(R.string.force_stop);
+ mUninstallButton = (Button) mFooter.findViewById(R.id.left_button);
+ mForceStopButton.setEnabled(false);
+ }
+
private Intent resolveIntent(Intent i) {
ResolveInfo result = getContext().getPackageManager().resolveActivity(i, 0);
return result != null ? new Intent(i.getAction())
@@ -511,8 +543,12 @@ public class InstalledAppDetails extends AppInfoBase
private void setAppLabelAndIcon(PackageInfo pkgInfo) {
final View appSnippet = mHeader.findViewById(R.id.app_snippet);
mState.ensureIcon(mAppEntry);
- setupAppSnippet(appSnippet, mAppEntry.label, mAppEntry.icon,
- pkgInfo != null ? pkgInfo.versionName : null);
+ if (mDashboardFeatureProvider.isEnabled()) {
+ mAppHeaderController.bindAppHeader(appSnippet, pkgInfo, mAppEntry);
+ } else {
+ setupAppSnippet(appSnippet, mAppEntry.label, mAppEntry.icon,
+ pkgInfo != null ? pkgInfo.versionName : null);
+ }
}
private boolean signaturesMatch(String pkg1, String pkg2) {
@@ -917,6 +953,12 @@ public class InstalledAppDetails extends AppInfoBase
}
addAppInstallerInfoPref(screen);
+ if (mDashboardFeatureProvider.isEnabled()) {
+ mFooter = new LayoutPreference(screen.getContext(), R.layout.app_action_buttons);
+ mFooter.setOrder(10000);
+ mFooter.setKey(KEY_FOOTER);
+ screen.addPreference(mFooter);
+ }
}
private void addAppInstallerInfoPref(PreferenceScreen screen) {
diff --git a/src/com/android/settings/dashboard/DashboardFeatureProviderImpl.java b/src/com/android/settings/dashboard/DashboardFeatureProviderImpl.java
index ed0520af511..d0c7c45d6b9 100644
--- a/src/com/android/settings/dashboard/DashboardFeatureProviderImpl.java
+++ b/src/com/android/settings/dashboard/DashboardFeatureProviderImpl.java
@@ -38,8 +38,8 @@ public class DashboardFeatureProviderImpl implements DashboardFeatureProvider {
private final CategoryManager mCategoryManager;
public DashboardFeatureProviderImpl(Context context) {
- mContext = context;
- mCategoryManager = CategoryManager.get(context);
+ mContext = context.getApplicationContext();
+ mCategoryManager = CategoryManager.get(mContext);
}
@Override
diff --git a/src/com/android/settings/overlay/FeatureFactory.java b/src/com/android/settings/overlay/FeatureFactory.java
index 35ec40f3a65..515975b8169 100644
--- a/src/com/android/settings/overlay/FeatureFactory.java
+++ b/src/com/android/settings/overlay/FeatureFactory.java
@@ -21,6 +21,7 @@ import android.text.TextUtils;
import android.util.Log;
import com.android.settings.R;
+import com.android.settings.applications.ApplicationFeatureProvider;
import com.android.settings.core.instrumentation.MetricsFeatureProvider;
import com.android.settings.dashboard.DashboardFeatureProvider;
import com.android.settings.fuelgauge.PowerUsageFeatureProvider;
@@ -71,6 +72,8 @@ public abstract class FeatureFactory {
public abstract DashboardFeatureProvider getDashboardFeatureProvider(Context context);
+ public abstract ApplicationFeatureProvider getApplicationFeatureProvider(Context context);
+
public abstract LocaleFeatureProvider getLocaleFeatureProvider();
diff --git a/src/com/android/settings/overlay/FeatureFactoryImpl.java b/src/com/android/settings/overlay/FeatureFactoryImpl.java
index 976ee3c0bc4..934021d996d 100644
--- a/src/com/android/settings/overlay/FeatureFactoryImpl.java
+++ b/src/com/android/settings/overlay/FeatureFactoryImpl.java
@@ -19,6 +19,8 @@ package com.android.settings.overlay;
import android.content.Context;
import android.support.annotation.Keep;
+import com.android.settings.applications.ApplicationFeatureProvider;
+import com.android.settings.applications.ApplicationFeatureProviderImpl;
import com.android.settings.core.instrumentation.MetricsFeatureProvider;
import com.android.settings.core.instrumentation.MetricsFeatureProviderImpl;
import com.android.settings.dashboard.DashboardFeatureProvider;
@@ -33,6 +35,7 @@ import com.android.settings.localepicker.LocaleFeatureProviderImpl;
@Keep
public final class FeatureFactoryImpl extends FeatureFactory {
+ private ApplicationFeatureProvider mApplicationFeatureProvider;
private MetricsFeatureProvider mMetricsFeatureProvider;
private DashboardFeatureProviderImpl mDashboardFeatureProvider;
private LocaleFeatureProvider mLocaleFeatureProvider;
@@ -63,6 +66,14 @@ public final class FeatureFactoryImpl extends FeatureFactory {
return mDashboardFeatureProvider;
}
+ @Override
+ public ApplicationFeatureProvider getApplicationFeatureProvider(Context context) {
+ if (mApplicationFeatureProvider == null) {
+ mApplicationFeatureProvider = new ApplicationFeatureProviderImpl(context);
+ }
+ return mApplicationFeatureProvider;
+ }
+
@Override
public LocaleFeatureProvider getLocaleFeatureProvider() {
if (mLocaleFeatureProvider == null) {
diff --git a/tests/robotests/src/com/android/settings/applications/AdvancedAppSettingsTest.java b/tests/robotests/src/com/android/settings/applications/AdvancedAppSettingsTest.java
index d0c58897735..7da30ed01ad 100644
--- a/tests/robotests/src/com/android/settings/applications/AdvancedAppSettingsTest.java
+++ b/tests/robotests/src/com/android/settings/applications/AdvancedAppSettingsTest.java
@@ -19,6 +19,7 @@ package com.android.settings.applications;
import android.content.Context;
import com.android.settings.R;
+import com.android.settings.SettingsRobolectricTestRunner;
import com.android.settings.TestConfig;
import com.android.settings.testutils.FakeFeatureFactory;
@@ -28,14 +29,13 @@ import org.junit.runner.RunWith;
import org.mockito.Answers;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
-import org.robolectric.RobolectricTestRunner;
import org.robolectric.annotation.Config;
import org.robolectric.shadows.ShadowApplication;
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.Mockito.when;
-@RunWith(RobolectricTestRunner.class)
+@RunWith(SettingsRobolectricTestRunner.class)
@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
public class AdvancedAppSettingsTest {
diff --git a/tests/robotests/src/com/android/settings/applications/AppHeaderControllerTest.java b/tests/robotests/src/com/android/settings/applications/AppHeaderControllerTest.java
new file mode 100644
index 00000000000..67320283d08
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/applications/AppHeaderControllerTest.java
@@ -0,0 +1,150 @@
+/*
+ * Copyright (C) 2016 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;
+
+
+import android.app.Fragment;
+import android.content.Context;
+import android.content.Intent;
+import android.content.pm.ActivityInfo;
+import android.content.pm.PackageInfo;
+import android.content.pm.ResolveInfo;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.widget.TextView;
+
+import com.android.settings.R;
+import com.android.settings.SettingsRobolectricTestRunner;
+import com.android.settings.TestConfig;
+import com.android.settingslib.applications.ApplicationsState;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Answers;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.robolectric.annotation.Config;
+import org.robolectric.shadows.ShadowApplication;
+
+import static com.google.common.truth.Truth.assertThat;
+import static org.mockito.Matchers.any;
+import static org.mockito.Matchers.anyInt;
+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 class AppHeaderControllerTest {
+
+ @Mock(answer = Answers.RETURNS_DEEP_STUBS)
+ private Context mContext;
+ @Mock(answer = Answers.RETURNS_DEEP_STUBS)
+ private ApplicationsState.AppEntry mAppEntry;
+ @Mock
+ private Fragment mFragment;
+
+ private Context mShadowContext;
+ private LayoutInflater mLayoutInflater;
+ private PackageInfo mInfo;
+ private AppHeaderController mController;
+
+
+ @Before
+ public void setUp() {
+ MockitoAnnotations.initMocks(this);
+ mShadowContext = ShadowApplication.getInstance().getApplicationContext();
+ mLayoutInflater = LayoutInflater.from(mShadowContext);
+ mInfo = new PackageInfo();
+ mInfo.versionName = "1234";
+ mController = new AppHeaderController(mContext);
+ }
+
+ @Test
+ public void bindViews_shouldBindAllData() {
+ final String testString = "test";
+ final View appHeader = mLayoutInflater.inflate(R.layout.app_details, null /* root */);
+ final TextView label = (TextView) appHeader.findViewById(android.R.id.title);
+ final TextView version = (TextView) appHeader.findViewById(android.R.id.summary);
+ label.setText(testString);
+ label.setText(testString);
+
+ mController.bindAppHeader(appHeader, mInfo, mAppEntry);
+
+ assertThat(label.getText()).isNotEqualTo(testString);
+ assertThat(version.getText())
+ .isEqualTo(mShadowContext.getString(R.string.version_text, mInfo.versionName));
+ }
+
+ @Test
+ public void bindButton_hasAppPref_shouldShowButton() {
+ final ResolveInfo info = new ResolveInfo();
+ info.activityInfo = new ActivityInfo();
+ info.activityInfo.packageName = "123";
+ info.activityInfo.name = "321";
+ final View appLinks = mLayoutInflater
+ .inflate(R.layout.app_details, null /* root */);
+ when(mContext.getPackageManager().resolveActivity(any(Intent.class), anyInt()))
+ .thenReturn(info);
+ mController.bindAppHeaderButtons(mFragment, appLinks,
+ mShadowContext.getPackageName(),
+ AppHeaderController.ActionType.ACTION_APP_PREFERENCE,
+ AppHeaderController.ActionType.ACTION_APP_PREFERENCE);
+ assertThat(appLinks.findViewById(R.id.left_button).getVisibility())
+ .isEqualTo(View.VISIBLE);
+ assertThat(appLinks.findViewById(R.id.right_button).getVisibility())
+ .isEqualTo(View.VISIBLE);
+ try {
+ appLinks.findViewById(R.id.left_button).performClick();
+ } catch (Exception e) {
+ // Ignore exception because the launching intent is fake.
+ }
+ verify(mFragment).startActivity(any(Intent.class));
+ }
+
+ @Test
+ public void bindButton_noAppPref_shouldNotShowButton() {
+ final View appLinks = mLayoutInflater
+ .inflate(R.layout.app_details, null /* root */);
+ when(mContext.getPackageManager().resolveActivity(any(Intent.class), anyInt()))
+ .thenReturn(null);
+ mController.bindAppHeaderButtons(mFragment, appLinks,
+ mShadowContext.getPackageName(),
+ AppHeaderController.ActionType.ACTION_APP_PREFERENCE,
+ AppHeaderController.ActionType.ACTION_APP_PREFERENCE);
+ assertThat(appLinks.findViewById(R.id.left_button).getVisibility())
+ .isEqualTo(View.GONE);
+ assertThat(appLinks.findViewById(R.id.right_button).getVisibility())
+ .isEqualTo(View.GONE);
+ }
+
+ @Test
+ public void bindButton_noStoreLink_shouldNotShowButton() {
+ final View appLinks = mLayoutInflater
+ .inflate(R.layout.app_details, null /* root */);
+ when(mContext.getPackageManager().resolveActivity(any(Intent.class), anyInt()))
+ .thenReturn(null);
+ mController.bindAppHeaderButtons(mFragment, appLinks,
+ mShadowContext.getPackageName(),
+ AppHeaderController.ActionType.ACTION_STORE_DEEP_LINK,
+ AppHeaderController.ActionType.ACTION_STORE_DEEP_LINK);
+ assertThat(appLinks.findViewById(R.id.left_button).getVisibility())
+ .isEqualTo(View.GONE);
+ assertThat(appLinks.findViewById(R.id.right_button).getVisibility())
+ .isEqualTo(View.GONE);
+ }
+}
diff --git a/tests/robotests/src/com/android/settings/testutils/FakeFeatureFactory.java b/tests/robotests/src/com/android/settings/testutils/FakeFeatureFactory.java
index 7bf908d137c..8241352d351 100644
--- a/tests/robotests/src/com/android/settings/testutils/FakeFeatureFactory.java
+++ b/tests/robotests/src/com/android/settings/testutils/FakeFeatureFactory.java
@@ -16,6 +16,8 @@
package com.android.settings.testutils;
import android.content.Context;
+
+import com.android.settings.applications.ApplicationFeatureProvider;
import com.android.settings.core.instrumentation.MetricsFeatureProvider;
import com.android.settings.dashboard.DashboardFeatureProvider;
import com.android.settings.fuelgauge.PowerUsageFeatureProvider;
@@ -38,6 +40,7 @@ public class FakeFeatureFactory extends FeatureFactory {
public final PowerUsageFeatureProvider powerUsageFeatureProvider;
public final DashboardFeatureProvider dashboardFeatureProvider;
public final LocaleFeatureProvider localeFeatureProvider;
+ public final ApplicationFeatureProvider applicationFeatureProvider;
/**
* Call this in {@code @Before} method of the test class to use fake factory.
@@ -65,6 +68,7 @@ public class FakeFeatureFactory extends FeatureFactory {
powerUsageFeatureProvider = mock(PowerUsageFeatureProvider.class);
dashboardFeatureProvider = mock(DashboardFeatureProvider.class);
localeFeatureProvider = mock(LocaleFeatureProvider.class);
+ applicationFeatureProvider = mock(ApplicationFeatureProvider.class);
}
@Override
@@ -87,6 +91,11 @@ public class FakeFeatureFactory extends FeatureFactory {
return dashboardFeatureProvider;
}
+ @Override
+ public ApplicationFeatureProvider getApplicationFeatureProvider(Context context) {
+ return applicationFeatureProvider;
+ }
+
@Override
public LocaleFeatureProvider getLocaleFeatureProvider() {
return localeFeatureProvider;