/* * 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 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 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(); } }