From e712aed3d729ab6e0cd85ceded029f8fcac5f50d Mon Sep 17 00:00:00 2001 From: Doris Ling Date: Thu, 14 Dec 2017 14:23:41 -0800 Subject: [PATCH] Add preference controller for app header view. - move code related to initializing/refreshing the app header from AppInfoDashboardFragment into a new controller. - this is the last preference logic in AppInfoDashboardFragment. With this change, the conversion into dashboad fragment will be considered as complete. - remaining work for the bug will be enable the feature flag and remove the obsolete InstalledAppDetails. Bug: 69384089 Test: make RunSettingsRoboTests Change-Id: I14056bf291278b2b36f9502177c84edd6a899d0f --- .../AppHeaderViewPreferenceController.java | 92 ++++++++++++++++++ .../appinfo/AppInfoDashboardFragment.java | 45 +-------- ...AppHeaderViewPreferenceControllerTest.java | 97 +++++++++++++++++++ 3 files changed, 193 insertions(+), 41 deletions(-) create mode 100644 src/com/android/settings/applications/appinfo/AppHeaderViewPreferenceController.java create mode 100644 tests/robotests/src/com/android/settings/applications/appinfo/AppHeaderViewPreferenceControllerTest.java diff --git a/src/com/android/settings/applications/appinfo/AppHeaderViewPreferenceController.java b/src/com/android/settings/applications/appinfo/AppHeaderViewPreferenceController.java new file mode 100644 index 00000000000..c644648cfb0 --- /dev/null +++ b/src/com/android/settings/applications/appinfo/AppHeaderViewPreferenceController.java @@ -0,0 +1,92 @@ +/* + * 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.Activity; +import android.content.Context; +import android.content.pm.PackageInfo; +import android.support.v7.preference.PreferenceScreen; + +import com.android.settings.R; +import com.android.settings.Utils; +import com.android.settings.applications.LayoutPreference; +import com.android.settings.core.BasePreferenceController; +import com.android.settings.widget.EntityHeaderController; +import com.android.settingslib.applications.AppUtils; +import com.android.settingslib.applications.ApplicationsState.AppEntry; +import com.android.settingslib.core.lifecycle.Lifecycle; + +public class AppHeaderViewPreferenceController extends BasePreferenceController + implements AppInfoDashboardFragment.Callback { + + private static final String KEY_HEADER = "header_view"; + + private LayoutPreference mHeader; + private final AppInfoDashboardFragment mParent; + private final String mPackageName; + private final Lifecycle mLifecycle; + + public AppHeaderViewPreferenceController(Context context, AppInfoDashboardFragment parent, + String packageName, Lifecycle lifecycle) { + super(context, KEY_HEADER); + mParent = parent; + mPackageName = packageName; + mLifecycle = lifecycle; + } + + @Override + public int getAvailabilityStatus() { + return AVAILABLE; + } + + @Override + public void displayPreference(PreferenceScreen screen) { + super.displayPreference(screen); + mHeader = (LayoutPreference) screen.findPreference(KEY_HEADER); + final Activity activity = mParent.getActivity(); + EntityHeaderController + .newInstance(activity, mParent, mHeader.findViewById(R.id.entity_header)) + .setRecyclerView(mParent.getListView(), mLifecycle) + .setPackageName(mPackageName) + .setHasAppInfoLink(false) + .setButtonActions(EntityHeaderController.ActionType.ACTION_APP_PREFERENCE, + EntityHeaderController.ActionType.ACTION_NONE) + .styleActionBar(activity) + .bindHeaderButtons(); + } + + @Override + public void refreshUi() { + setAppLabelAndIcon(mParent.getPackageInfo(), mParent.getAppEntry()); + } + + // Utility method to set application label and icon. + private void setAppLabelAndIcon(PackageInfo pkgInfo, AppEntry appEntry) { + final Activity activity = mParent.getActivity(); + final boolean isInstantApp = AppUtils.isInstant(pkgInfo.applicationInfo); + final CharSequence summary = isInstantApp + ? null : mContext.getString(Utils.getInstallationStatus(appEntry.info)); + EntityHeaderController + .newInstance(activity, mParent, mHeader.findViewById(R.id.entity_header)) + .setLabel(appEntry) + .setIcon(appEntry) + .setSummary(summary) + .setIsInstantApp(isInstantApp) + .done(activity, false /* rebindActions */); + } + +} diff --git a/src/com/android/settings/applications/appinfo/AppInfoDashboardFragment.java b/src/com/android/settings/applications/appinfo/AppInfoDashboardFragment.java index 57e2b0c1f84..41c1f7ce05b 100755 --- a/src/com/android/settings/applications/appinfo/AppInfoDashboardFragment.java +++ b/src/com/android/settings/applications/appinfo/AppInfoDashboardFragment.java @@ -107,7 +107,6 @@ public class AppInfoDashboardFragment extends DashboardFragment private static final int DLG_DISABLE = DLG_BASE + 2; private static final int DLG_SPECIAL_DISABLE = DLG_BASE + 3; - private static final String KEY_HEADER = "header_view"; private static final String KEY_ADVANCED_APP_INFO_CATEGORY = "advanced_app_info"; public static final String ARG_PACKAGE_NAME = "package"; @@ -135,7 +134,6 @@ public class AppInfoDashboardFragment extends DashboardFragment private boolean mInitialized; private boolean mShowUninstalled; - private LayoutPreference mHeader; private boolean mUpdatedSysApp = false; private boolean mDisableAfterUninstall; @@ -213,6 +211,8 @@ public class AppInfoDashboardFragment extends DashboardFragment // The following are controllers for preferences that needs to refresh the preference state // when app state changes. + controllers.add( + new AppHeaderViewPreferenceController(context, this, packageName, lifecycle)); controllers.add(new AppStoragePreferenceController(context, this, lifecycle)); controllers.add(new AppDataUsagePreferenceController(context, this, lifecycle)); controllers.add(new AppNotificationPreferenceController(context, this)); @@ -275,25 +275,6 @@ public class AppInfoDashboardFragment extends DashboardFragment return mPackageInfo; } - @Override - public void onActivityCreated(Bundle savedInstanceState) { - super.onActivityCreated(savedInstanceState); - if (mFinishing) { - return; - } - final Activity activity = getActivity(); - mHeader = (LayoutPreference) findPreference(KEY_HEADER); - EntityHeaderController.newInstance(activity, this, mHeader.findViewById(R.id.entity_header)) - .setRecyclerView(getListView(), getLifecycle()) - .setPackageName(mPackageName) - .setHasAppInfoLink(false) - .setButtonActions(EntityHeaderController.ActionType.ACTION_APP_PREFERENCE, - EntityHeaderController.ActionType.ACTION_NONE) - .styleActionBar(activity) - .bindHeaderButtons(); - - } - @Override public void onPackageSizeChanged(String packageName) { if (!TextUtils.equals(packageName, mPackageName)) { @@ -382,22 +363,6 @@ public class AppInfoDashboardFragment extends DashboardFragment } } - // Utility method to set application label and icon. - private void setAppLabelAndIcon(PackageInfo pkgInfo) { - final View appSnippet = mHeader.findViewById(R.id.entity_header); - mState.ensureIcon(mAppEntry); - final Activity activity = getActivity(); - final boolean isInstantApp = AppUtils.isInstant(mPackageInfo.applicationInfo); - final CharSequence summary = - isInstantApp ? null : getString(Utils.getInstallationStatus(mAppEntry.info)); - EntityHeaderController.newInstance(activity, this, appSnippet) - .setLabel(mAppEntry) - .setIcon(mAppEntry) - .setSummary(summary) - .setIsInstantApp(isInstantApp) - .done(activity, false /* rebindActions */); - } - @VisibleForTesting boolean shouldShowUninstallForAll(AppEntry appEntry) { boolean showIt = true; @@ -433,11 +398,9 @@ public class AppInfoDashboardFragment extends DashboardFragment return false; // onCreate must have failed, make sure to exit } - - setAppLabelAndIcon(mPackageInfo); + mState.ensureIcon(mAppEntry); // Update the preference summaries. - final Activity context = getActivity(); for (Callback callback : mCallbacks) { callback.refreshUi(); } @@ -450,7 +413,7 @@ public class AppInfoDashboardFragment extends DashboardFragment // All other times: if the app no longer exists then we want // to go away. try { - final ApplicationInfo ainfo = context.getPackageManager().getApplicationInfo( + final ApplicationInfo ainfo = getActivity().getPackageManager().getApplicationInfo( mAppEntry.info.packageName, PackageManager.MATCH_DISABLED_COMPONENTS | PackageManager.MATCH_ANY_USER); diff --git a/tests/robotests/src/com/android/settings/applications/appinfo/AppHeaderViewPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/applications/appinfo/AppHeaderViewPreferenceControllerTest.java new file mode 100644 index 00000000000..286469c348a --- /dev/null +++ b/tests/robotests/src/com/android/settings/applications/appinfo/AppHeaderViewPreferenceControllerTest.java @@ -0,0 +1,97 @@ +/* + * 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 org.mockito.Mockito.mock; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +import android.app.Activity; +import android.content.Context; +import android.content.pm.ApplicationInfo; +import android.content.pm.PackageInfo; +import android.support.v7.preference.PreferenceScreen; +import android.view.View; +import android.widget.TextView; + +import com.android.settings.R; +import com.android.settings.TestConfig; +import com.android.settings.applications.LayoutPreference; +import com.android.settings.testutils.SettingsRobolectricTestRunner; +import com.android.settingslib.applications.ApplicationsState; + +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 AppHeaderViewPreferenceControllerTest { + + @Mock + private AppInfoDashboardFragment mFragment; + @Mock + private Activity mActivity; + + private Context mContext; + private AppHeaderViewPreferenceController mController; + + @Before + public void setUp() { + MockitoAnnotations.initMocks(this); + mContext = RuntimeEnvironment.application; + when(mFragment.getActivity()).thenReturn(mActivity); + when(mActivity.getApplicationContext()).thenReturn(mContext); + mController = new AppHeaderViewPreferenceController(mContext, mFragment, "Package1", null); + } + + @Test + public void refreshUi_shouldRefreshButton() { + final PackageInfo packageInfo = mock(PackageInfo.class); + final ApplicationsState.AppEntry appEntry = mock(ApplicationsState.AppEntry.class); + final String appLabel = "App1"; + appEntry.label = appLabel; + final ApplicationInfo info = new ApplicationInfo(); + info.flags = ApplicationInfo.FLAG_INSTALLED; + info.enabled = true; + packageInfo.applicationInfo = info; + appEntry.info = info; + when(mFragment.getAppEntry()).thenReturn(appEntry); + when(mFragment.getPackageInfo()).thenReturn(packageInfo); + + final PreferenceScreen screen = mock(PreferenceScreen.class); + final LayoutPreference preference = mock(LayoutPreference.class); + when(screen.findPreference(mController.getPreferenceKey())).thenReturn(preference); + final View header = mock(View.class); + when(preference.findViewById(R.id.entity_header)).thenReturn(header); + final TextView title = mock(TextView.class); + when(header.findViewById(R.id.entity_header_title)).thenReturn(title); + final TextView summary = mock(TextView.class); + when(header.findViewById(R.id.entity_header_summary)).thenReturn(summary); + mController.displayPreference(screen); + + mController.refreshUi(); + + verify(title).setText(appLabel); + verify(summary).setText(mContext.getString(R.string.installed)); + } + +}