Remove silky flag from Apps for official release

Remove the silky condition and clean up redundant files.

Bug: 183670633
Test: robotests & visual with turning on/off silky home
Change-Id: If6df8a4191d5750edca22dd94b99c43ccebf2e04
This commit is contained in:
Yanting Yang
2021-05-25 02:35:58 +08:00
parent 31389702ad
commit ba8e5802d4
10 changed files with 2 additions and 803 deletions

View File

@@ -3317,15 +3317,6 @@
</intent-filter>
</activity>
<activity
android:name=".Settings$AppAndNotificationDashboardActivity"
android:label="@string/app_and_notification_dashboard_title"
android:icon="@drawable/ic_homepage_apps"
android:exported="true">
<meta-data android:name="com.android.settings.FRAGMENT_CLASS"
android:value="com.android.settings.applications.AppAndNotificationDashboardFragment"/>
</activity>
<activity
android:name=".Settings$AppDashboardActivity"
android:label="@string/apps_dashboard_title"

View File

@@ -1,114 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
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.
-->
<PreferenceScreen
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:settings="http://schemas.android.com/apk/res-auto"
android:key="apps_and_notification_screen"
android:title="@string/app_and_notification_dashboard_title"
settings:initialExpandedChildrenCount="4">
<!-- the initial count should include the dynamic tiles -->
<Preference
android:key="all_app_info"
android:title="@string/applications_settings"
android:order="-999"
android:fragment="com.android.settings.applications.manageapplications.ManageApplications"
settings:controller="com.android.settings.applications.AllAppsInfoPreferenceController"
settings:keywords="@string/keywords_applications_settings"/>
<com.android.settingslib.widget.LayoutPreference
android:key="recent_open_apps"
android:title="@string/recent_app_category_title"
android:layout="@layout/app_entities_header"
android:selectable="false"
android:order="-998"
settings:allowDividerBelow="true"
settings:controller="com.android.settings.applications.RecentAppsPreferenceController"/>
<!-- Empty category to draw divider -->
<PreferenceCategory
android:key="recent_apps_divider"
android:layout="@layout/preference_category_no_label"
android:order="-997"/>
<Preference
android:key="conversations"
android:title="@string/conversations_category_title"
android:order="-550"
settings:controller="com.android.settings.notification.ConversationListSummaryPreferenceController"
android:fragment="com.android.settings.notification.app.ConversationListSettings"
/>
<Preference
android:key="configure_notification_settings"
android:title="@string/configure_notification_settings"
android:summary="@string/notification_screen_summary"
android:order="-440"
android:fragment="com.android.settings.notification.ConfigureNotificationSettings"/>
<!-- Notifications (appears before manage_perms), default apps (appears after) -->
<PreferenceCategory
android:key="dashboard_tile_placeholder"
android:order="10"/>
<Preference
android:key="default_apps"
android:title="@string/app_default_dashboard_title"
android:order="11"
settings:controller="com.android.settings.applications.DefaultAppsPreferenceController">
<intent android:action="android.settings.MANAGE_DEFAULT_APPS_SETTINGS"/>
</Preference>
<Preference
android:key="manage_perms"
android:title="@string/app_permissions"
android:summary="@string/runtime_permissions_summary_control_app_access"
android:order="12"
settings:keywords="@string/keywords_app_permissions">
<intent android:action="android.intent.action.MANAGE_PERMISSIONS"/>
</Preference>
<Preference
android:key="hibernated_apps"
android:title="@string/unused_apps"
android:summary="@string/summary_placeholder"
android:order="13"
settings:keywords="app_hibernation_key"
settings:controller="com.android.settings.applications.HibernatedAppsPreferenceController">
<intent android:action="android.intent.action.MANAGE_UNUSED_APPS"/>
</Preference>
<com.android.settingslib.RestrictedPreference
android:key="app_and_notif_cell_broadcast_settings"
android:title="@string/cell_broadcast_settings"
android:order="15"
settings:useAdminDisabledSummary="true">
<intent
android:action="android.intent.action.MAIN"
android:targetPackage="@string/config_cell_broadcast_receiver_package"
android:targetClass="com.android.cellbroadcastreceiver.CellBroadcastSettings"/>
</com.android.settingslib.RestrictedPreference>
<Preference
android:key="special_access"
android:fragment="com.android.settings.applications.specialaccess.SpecialAccessSettings"
android:title="@string/special_access"
android:order="20"
settings:controller="com.android.settings.applications.SpecialAppAccessPreferenceController"/>
</PreferenceScreen>

View File

@@ -1,73 +0,0 @@
/*
* Copyright (C) 2019 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.usage.UsageStats;
import android.content.Context;
import androidx.annotation.NonNull;
import androidx.annotation.VisibleForTesting;
import androidx.preference.Preference;
import androidx.preference.PreferenceScreen;
import com.android.settings.R;
import com.android.settings.core.BasePreferenceController;
import java.util.List;
public class AllAppsInfoPreferenceController extends BasePreferenceController
implements RecentAppStatsMixin.RecentAppStatsListener {
@VisibleForTesting
Preference mPreference;
public AllAppsInfoPreferenceController(Context context, String key) {
super(context, key);
}
@Override
public int getAvailabilityStatus() {
return AVAILABLE;
}
@Override
public void displayPreference(PreferenceScreen screen) {
super.displayPreference(screen);
mPreference = screen.findPreference(getPreferenceKey());
// In most cases, device has recently opened apps. So, we hide it by default.
mPreference.setVisible(false);
}
@Override
public void onReloadDataCompleted(@NonNull List<UsageStats> recentApps) {
// If device has recently opened apps, we don't show all apps preference.
if (!recentApps.isEmpty()) {
mPreference.setVisible(false);
return;
}
mPreference.setVisible(true);
// Show total number of installed apps as See all's summary.
new InstalledAppCounter(mContext, InstalledAppCounter.IGNORE_INSTALL_REASON,
mContext.getPackageManager()) {
@Override
protected void onCountComplete(int num) {
mPreference.setSummary(mContext.getString(R.string.apps_summary, num));
}
}.execute();
}
}

View File

@@ -1,151 +0,0 @@
/*
* 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.settings.SettingsEnums;
import android.app.usage.UsageStats;
import android.content.Context;
import android.os.Bundle;
import android.provider.SearchIndexableResource;
import android.util.FeatureFlagUtils;
import android.view.View;
import androidx.annotation.NonNull;
import com.android.settings.R;
import com.android.settings.Utils;
import com.android.settings.core.FeatureFlags;
import com.android.settings.dashboard.DashboardFragment;
import com.android.settings.notification.EmergencyBroadcastPreferenceController;
import com.android.settings.search.BaseSearchIndexProvider;
import com.android.settingslib.core.AbstractPreferenceController;
import com.android.settingslib.search.SearchIndexable;
import com.android.settingslib.widget.AppEntitiesHeaderController;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
@SearchIndexable
public class AppAndNotificationDashboardFragment extends DashboardFragment
implements RecentAppStatsMixin.RecentAppStatsListener {
private static final String TAG = "AppAndNotifDashboard";
private RecentAppStatsMixin mRecentAppStatsMixin;
private RecentAppsPreferenceController mRecentAppsPreferenceController;
private AllAppsInfoPreferenceController mAllAppsInfoPreferenceController;
@Override
public int getMetricsCategory() {
return SettingsEnums.SETTINGS_APP_NOTIF_CATEGORY;
}
@Override
protected String getLogTag() {
return TAG;
}
@Override
public int getHelpResource() {
return R.string.help_url_apps_and_notifications;
}
@Override
protected int getPreferenceScreenResId() {
return R.xml.app_and_notification;
}
@Override
public void onAttach(Context context) {
super.onAttach(context);
use(SpecialAppAccessPreferenceController.class).setSession(getSettingsLifecycle());
mRecentAppStatsMixin = new RecentAppStatsMixin(context,
AppEntitiesHeaderController.MAXIMUM_APPS);
getSettingsLifecycle().addObserver(mRecentAppStatsMixin);
mRecentAppStatsMixin.addListener(this);
mRecentAppsPreferenceController = use(RecentAppsPreferenceController.class);
mRecentAppsPreferenceController.setFragment(this /* fragment */);
mRecentAppStatsMixin.addListener(mRecentAppsPreferenceController);
mAllAppsInfoPreferenceController = use(AllAppsInfoPreferenceController.class);
mRecentAppStatsMixin.addListener(mAllAppsInfoPreferenceController);
}
@Override
public void onViewCreated(View view, Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
setPinnedHeaderView(R.layout.progress_header);
showPinnedHeader(false);
}
@Override
public void onStart() {
super.onStart();
showPinnedHeader(true);
}
@Override
public void onReloadDataCompleted(@NonNull List<UsageStats> recentApps) {
showPinnedHeader(false);
if (!recentApps.isEmpty()) {
Utils.setActionBarShadowAnimation(getActivity(), getSettingsLifecycle(),
getListView());
}
}
@Override
protected List<AbstractPreferenceController> createPreferenceControllers(Context context) {
return buildPreferenceControllers(context);
}
private static List<AbstractPreferenceController> buildPreferenceControllers(Context context) {
final List<AbstractPreferenceController> controllers = new ArrayList<>();
controllers.add(new EmergencyBroadcastPreferenceController(context,
"app_and_notif_cell_broadcast_settings"));
return controllers;
}
public static final BaseSearchIndexProvider SEARCH_INDEX_DATA_PROVIDER =
new BaseSearchIndexProvider() {
@Override
public List<SearchIndexableResource> getXmlResourcesToIndex(
Context context, boolean enabled) {
final SearchIndexableResource sir = new SearchIndexableResource(context);
sir.xmlResId = R.xml.app_and_notification;
return Arrays.asList(sir);
}
@Override
public List<AbstractPreferenceController> createPreferenceControllers(
Context context) {
return buildPreferenceControllers(context);
}
@Override
protected boolean isPageSearchEnabled(Context context) {
// TODO(b/174964405): This method should be removed when silky home launched.
// This page is going to deprecate, we should make this page unsearchable
// when the silky home is enabled, otherwise search results will contain the
// old data and launch this page even if the silky home is enabled.
return !FeatureFlagUtils.isEnabled(context, FeatureFlags.SILKY_HOME);
}
};
}

View File

@@ -19,14 +19,11 @@ package com.android.settings.applications;
import android.app.settings.SettingsEnums;
import android.content.Context;
import android.provider.SearchIndexableResource;
import android.util.FeatureFlagUtils;
import com.android.settings.R;
import com.android.settings.core.FeatureFlags;
import com.android.settings.dashboard.DashboardFragment;
import com.android.settings.search.BaseSearchIndexProvider;
import com.android.settingslib.core.AbstractPreferenceController;
import com.android.settingslib.drawer.CategoryKey;
import com.android.settingslib.search.SearchIndexable;
import java.util.ArrayList;
@@ -79,16 +76,6 @@ public class AppDashboardFragment extends DashboardFragment {
return buildPreferenceControllers(context);
}
@Override
public String getCategoryKey() {
// TODO(b/174964405): Remove this function when the silky flag was deprecated.
// To include injection tiles, map this app fragment to the app category in the short term.
// When we deprecate the silky flag, we have to:
// 1. Remove this method.
// 2. Update the mapping in DashboardFragmentRegistry.PARENT_TO_CATEGORY_KEY_MAP.
return CategoryKey.CATEGORY_APPS;
}
public static final BaseSearchIndexProvider SEARCH_INDEX_DATA_PROVIDER =
new BaseSearchIndexProvider() {
@Override
@@ -104,12 +91,5 @@ public class AppDashboardFragment extends DashboardFragment {
Context context) {
return buildPreferenceControllers(context);
}
@Override
protected boolean isPageSearchEnabled(Context context) {
// TODO(b/174964405): This method should be removed when silky home launched.
// Only allow this page can be searchable when silky home enabled.
return FeatureFlagUtils.isEnabled(context, FeatureFlags.SILKY_HOME);
}
};
}

View File

@@ -1,176 +0,0 @@
/*
* 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;
import android.app.Application;
import android.app.usage.UsageStats;
import android.content.Context;
import android.icu.text.RelativeDateTimeFormatter;
import android.os.UserHandle;
import android.view.View;
import androidx.annotation.NonNull;
import androidx.annotation.VisibleForTesting;
import androidx.fragment.app.Fragment;
import androidx.preference.Preference;
import androidx.preference.PreferenceScreen;
import com.android.settings.R;
import com.android.settings.applications.appinfo.AppInfoDashboardFragment;
import com.android.settings.applications.manageapplications.ManageApplications;
import com.android.settings.core.BasePreferenceController;
import com.android.settings.core.SubSettingLauncher;
import com.android.settings.overlay.FeatureFactory;
import com.android.settingslib.Utils;
import com.android.settingslib.applications.ApplicationsState;
import com.android.settingslib.core.instrumentation.MetricsFeatureProvider;
import com.android.settingslib.utils.StringUtil;
import com.android.settingslib.widget.AppEntitiesHeaderController;
import com.android.settingslib.widget.AppEntityInfo;
import com.android.settingslib.widget.LayoutPreference;
import java.util.List;
/**
* This controller displays up to three recently used apps.
* If there is no recently used app, we only show up an "App Info" preference.
*/
public class RecentAppsPreferenceController extends BasePreferenceController
implements RecentAppStatsMixin.RecentAppStatsListener {
@VisibleForTesting
static final String KEY_DIVIDER = "recent_apps_divider";
@VisibleForTesting
AppEntitiesHeaderController mAppEntitiesController;
@VisibleForTesting
LayoutPreference mRecentAppsPreference;
@VisibleForTesting
Preference mDivider;
private final ApplicationsState mApplicationsState;
private final int mUserId;
private final MetricsFeatureProvider mMetricsFeatureProvider;
private Fragment mHost;
private List<UsageStats> mRecentApps;
public RecentAppsPreferenceController(Context context, String key) {
super(context, key);
mApplicationsState = ApplicationsState.getInstance(
(Application) mContext.getApplicationContext());
mUserId = UserHandle.myUserId();
mMetricsFeatureProvider = FeatureFactory.getFactory(mContext).getMetricsFeatureProvider();
}
public void setFragment(Fragment fragment) {
mHost = fragment;
}
@Override
public int getAvailabilityStatus() {
return AVAILABLE_UNSEARCHABLE;
}
@Override
public void displayPreference(PreferenceScreen screen) {
super.displayPreference(screen);
mDivider = screen.findPreference(KEY_DIVIDER);
mRecentAppsPreference = screen.findPreference(getPreferenceKey());
final View view = mRecentAppsPreference.findViewById(R.id.app_entities_header);
mAppEntitiesController = AppEntitiesHeaderController.newInstance(mContext, view)
.setHeaderTitleRes(R.string.recent_app_category_title)
.setHeaderDetailsClickListener((View v) -> {
mMetricsFeatureProvider.logClickedPreference(mRecentAppsPreference,
getMetricsCategory());
new SubSettingLauncher(mContext)
.setDestination(ManageApplications.class.getName())
.setArguments(null /* arguments */)
.setTitleRes(R.string.application_info_label)
.setSourceMetricsCategory(getMetricsCategory())
.launch();
});
}
@Override
public void onReloadDataCompleted(@NonNull List<UsageStats> recentApps) {
mRecentApps = recentApps;
refreshUi();
// Show total number of installed apps as See all's summary.
new InstalledAppCounter(mContext, InstalledAppCounter.IGNORE_INSTALL_REASON,
mContext.getPackageManager()) {
@Override
protected void onCountComplete(int num) {
mAppEntitiesController.setHeaderDetails(
mContext.getResources().getQuantityString(R.plurals.see_all_apps_title,
num, num));
mAppEntitiesController.apply();
}
}.execute();
}
private void refreshUi() {
if (!mRecentApps.isEmpty()) {
displayRecentApps();
mRecentAppsPreference.setVisible(true);
mDivider.setVisible(true);
} else {
mDivider.setVisible(false);
mRecentAppsPreference.setVisible(false);
}
}
private void displayRecentApps() {
int showAppsCount = 0;
for (UsageStats stat : mRecentApps) {
final AppEntityInfo appEntityInfoInfo = createAppEntity(stat);
if (appEntityInfoInfo != null) {
mAppEntitiesController.setAppEntity(showAppsCount++, appEntityInfoInfo);
}
if (showAppsCount == AppEntitiesHeaderController.MAXIMUM_APPS) {
break;
}
}
}
private AppEntityInfo createAppEntity(UsageStats stat) {
final String pkgName = stat.getPackageName();
final ApplicationsState.AppEntry appEntry =
mApplicationsState.getEntry(pkgName, mUserId);
if (appEntry == null) {
return null;
}
return new AppEntityInfo.Builder()
.setIcon(Utils.getBadgedIcon(mContext, appEntry.info))
.setTitle(appEntry.label)
.setSummary(StringUtil.formatRelativeTime(mContext,
System.currentTimeMillis() - stat.getLastTimeUsed(), false,
RelativeDateTimeFormatter.Style.SHORT))
.setOnClickListener(v -> {
mMetricsFeatureProvider.logClickedPreference(mRecentAppsPreference,
getMetricsCategory());
AppInfoBase.startAppInfoFragment(AppInfoDashboardFragment.class,
R.string.application_info_label, pkgName, appEntry.info.uid,
mHost, 1001 /*RequestCode*/, getMetricsCategory());
})
.build();
}
}

View File

@@ -35,7 +35,6 @@ import com.android.settings.accounts.AccountDashboardFragment;
import com.android.settings.accounts.AccountSyncSettings;
import com.android.settings.accounts.ChooseAccountFragment;
import com.android.settings.accounts.ManagedProfileSettings;
import com.android.settings.applications.AppAndNotificationDashboardFragment;
import com.android.settings.applications.AppDashboardFragment;
import com.android.settings.applications.ProcessStatsSummary;
import com.android.settings.applications.ProcessStatsUi;
@@ -293,7 +292,6 @@ public class SettingsGateway {
NetworkDashboardFragment.class.getName(),
ConnectedDeviceDashboardFragment.class.getName(),
UsbDetailsFragment.class.getName(),
AppAndNotificationDashboardFragment.class.getName(),
AppDashboardFragment.class.getName(),
WifiCallingDisclaimerFragment.class.getName(),
AccountDashboardFragment.class.getName(),

View File

@@ -22,7 +22,7 @@ import com.android.settings.DisplaySettings;
import com.android.settings.LegalSettings;
import com.android.settings.accounts.AccountDashboardFragment;
import com.android.settings.accounts.AccountDetailDashboardFragment;
import com.android.settings.applications.AppAndNotificationDashboardFragment;
import com.android.settings.applications.AppDashboardFragment;
import com.android.settings.connecteddevice.AdvancedConnectedDeviceDashboardFragment;
import com.android.settings.connecteddevice.ConnectedDeviceDashboardFragment;
import com.android.settings.development.DevelopmentSettingsDashboardFragment;
@@ -76,7 +76,7 @@ public class DashboardFragmentRegistry {
CategoryKey.CATEGORY_CONNECT);
PARENT_TO_CATEGORY_KEY_MAP.put(AdvancedConnectedDeviceDashboardFragment.class.getName(),
CategoryKey.CATEGORY_DEVICE);
PARENT_TO_CATEGORY_KEY_MAP.put(AppAndNotificationDashboardFragment.class.getName(),
PARENT_TO_CATEGORY_KEY_MAP.put(AppDashboardFragment.class.getName(),
CategoryKey.CATEGORY_APPS);
PARENT_TO_CATEGORY_KEY_MAP.put(PowerUsageSummary.class.getName(),
CategoryKey.CATEGORY_BATTERY);

View File

@@ -1,89 +0,0 @@
/*
* Copyright (C) 2019 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 static com.android.settings.core.BasePreferenceController.AVAILABLE;
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.when;
import android.app.usage.UsageStats;
import android.content.Context;
import android.os.UserManager;
import androidx.preference.Preference;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.robolectric.RobolectricTestRunner;
import org.robolectric.RuntimeEnvironment;
import java.util.ArrayList;
import java.util.List;
@RunWith(RobolectricTestRunner.class)
public class AllAppsInfoPreferenceControllerTest {
@Mock
private UserManager mUserManager;
private AllAppsInfoPreferenceController mController;
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
final Context context = spy(RuntimeEnvironment.application);
final Preference preference = new Preference(context);
doReturn(mUserManager).when(context).getSystemService(Context.USER_SERVICE);
when(mUserManager.getProfileIdsWithDisabled(anyInt())).thenReturn(new int[]{});
mController = new AllAppsInfoPreferenceController(context, "test_key");
mController.mPreference = preference;
}
@Test
public void getAvailabilityStatus_shouldReturnAVAILABLE() {
assertThat(mController.getAvailabilityStatus()).isEqualTo(AVAILABLE);
}
@Test
public void onReloadDataCompleted_recentAppsSet_hidePreference() {
final List<UsageStats> stats = new ArrayList<>();
final UsageStats stat1 = new UsageStats();
stat1.mLastTimeUsed = System.currentTimeMillis();
stat1.mPackageName = "pkg.class";
stats.add(stat1);
mController.onReloadDataCompleted(stats);
assertThat(mController.mPreference.isVisible()).isFalse();
}
@Test
public void onReloadDataCompleted_noRecentAppSet_showPreference() {
final List<UsageStats> stats = new ArrayList<>();
mController.onReloadDataCompleted(stats);
assertThat(mController.mPreference.isVisible()).isTrue();
}
}

View File

@@ -1,167 +0,0 @@
/*
* 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;
import static com.android.settings.core.BasePreferenceController.AVAILABLE_UNSEARCHABLE;
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.mock;
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.usage.UsageStats;
import android.content.Context;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.os.UserHandle;
import android.os.UserManager;
import android.view.LayoutInflater;
import android.view.View;
import androidx.fragment.app.Fragment;
import androidx.preference.Preference;
import androidx.preference.PreferenceScreen;
import com.android.settings.R;
import com.android.settingslib.applications.ApplicationsState;
import com.android.settingslib.widget.AppEntitiesHeaderController;
import com.android.settingslib.widget.AppEntityInfo;
import com.android.settingslib.widget.LayoutPreference;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.robolectric.RobolectricTestRunner;
import org.robolectric.RuntimeEnvironment;
import org.robolectric.util.ReflectionHelpers;
import java.util.ArrayList;
import java.util.List;
@RunWith(RobolectricTestRunner.class)
public class RecentAppsPreferenceControllerTest {
@Mock
private PreferenceScreen mScreen;
@Mock
private UserManager mUserManager;
@Mock
private ApplicationsState mAppState;
@Mock
private PackageManager mPackageManager;
@Mock
private ApplicationsState.AppEntry mAppEntry;
@Mock
private ApplicationInfo mApplicationInfo;
@Mock
private Fragment mFragment;
private RecentAppsPreferenceController mController;
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
final Context context = spy(RuntimeEnvironment.application);
when(context.getApplicationContext()).thenReturn(context);
ReflectionHelpers.setStaticField(ApplicationsState.class, "sInstance", mAppState);
doReturn(mUserManager).when(context).getSystemService(Context.USER_SERVICE);
doReturn(mPackageManager).when(context).getPackageManager();
when(mUserManager.getProfileIdsWithDisabled(anyInt())).thenReturn(new int[]{});
final View appEntitiesHeaderView = LayoutInflater.from(context).inflate(
R.layout.app_entities_header, null /* root */);
final Preference dividerPreference = new Preference(context);
final LayoutPreference recentAppsPreference =
spy(new LayoutPreference(context, appEntitiesHeaderView));
mController = spy(new RecentAppsPreferenceController(context, "test_key"));
mController.setFragment(mFragment);
mController.mAppEntitiesController = mock(AppEntitiesHeaderController.class);
mController.mRecentAppsPreference = recentAppsPreference;
mController.mDivider = dividerPreference;
when(mScreen.findPreference(RecentAppsPreferenceController.KEY_DIVIDER))
.thenReturn(dividerPreference);
when(mScreen.findPreference("test_key")).thenReturn(recentAppsPreference);
when(recentAppsPreference.findViewById(R.id.app_entities_header)).thenReturn(
appEntitiesHeaderView);
}
@Test
public void getAvailabilityStatus_shouldReturnAVAILABLE_UNSEARCHABLE() {
assertThat(mController.getAvailabilityStatus()).isEqualTo(AVAILABLE_UNSEARCHABLE);
}
@Test
public void displayPreference_shouldSetupAppEntitiesHeaderController() {
mController.displayPreference(mScreen);
assertThat(mController.mAppEntitiesController).isNotNull();
}
@Test
public void onReloadDataCompleted_threeValidRecentOpenAppsSet_setAppEntityThreeTime() {
final List<UsageStats> stats = new ArrayList<>();
final UsageStats stat1 = new UsageStats();
final UsageStats stat2 = new UsageStats();
final UsageStats stat3 = new UsageStats();
stat1.mLastTimeUsed = System.currentTimeMillis();
stat1.mPackageName = "pkg.class";
stats.add(stat1);
stat2.mLastTimeUsed = System.currentTimeMillis();
stat2.mPackageName = "pkg.class2";
stats.add(stat2);
stat3.mLastTimeUsed = System.currentTimeMillis();
stat3.mPackageName = "pkg.class3";
stats.add(stat3);
when(mAppState.getEntry(stat1.mPackageName, UserHandle.myUserId()))
.thenReturn(mAppEntry);
when(mAppState.getEntry(stat2.mPackageName, UserHandle.myUserId()))
.thenReturn(mAppEntry);
when(mAppState.getEntry(stat3.mPackageName, UserHandle.myUserId()))
.thenReturn(mAppEntry);
mAppEntry.info = mApplicationInfo;
mController.onReloadDataCompleted(stats);
verify(mController.mAppEntitiesController, times(3))
.setAppEntity(anyInt(), any(AppEntityInfo.class));
assertThat(mController.mRecentAppsPreference.isVisible()).isTrue();
assertThat(mController.mDivider.isVisible()).isTrue();
}
@Test
public void onReloadDataCompleted_noRecentOpenAppsSet_shouldHideRecentAppPreference() {
final List<UsageStats> stats = new ArrayList<>();
mController.onReloadDataCompleted(stats);
assertThat(mController.mRecentAppsPreference.isVisible()).isFalse();
assertThat(mController.mDivider.isVisible()).isFalse();
}
}