/* * Copyright (C) 2022 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.launcher3.taskbar; import android.app.ActivityManager; import android.content.ComponentName; import android.util.SparseArray; import com.android.launcher3.model.data.AppInfo; import com.android.launcher3.model.data.ItemInfo; import com.android.launcher3.model.data.WorkspaceItemInfo; import com.android.quickstep.RecentsModel; import java.util.ArrayList; import java.util.Arrays; import java.util.HashSet; import java.util.Set; /** * Provides recent apps functionality specifically in a desktop environment. */ public class DesktopTaskbarRecentAppsController extends TaskbarRecentAppsController { private final TaskbarActivityContext mContext; private ArrayList mRunningApps = new ArrayList<>(); private AppInfo[] mApps; public DesktopTaskbarRecentAppsController(TaskbarActivityContext context) { mContext = context; } @Override protected void onDestroy() { super.onDestroy(); mApps = null; } @Override protected void setApps(AppInfo[] apps) { mApps = apps; } @Override protected boolean isEnabled() { return true; } /** * Set mRunningApps to hold currently running applications using the list of currently running * tasks. Filtering is also done to ignore applications that are already on the taskbar in the * original hotseat. */ @Override protected void updateRunningApps(SparseArray hotseatItems) { ArrayList runningApps = getRunningAppsFromTasks(); ArrayList filteredRunningApps = new ArrayList<>(); for (AppInfo runningApp : runningApps) { boolean shouldAddOnTaskbar = true; for (int i = 0; i < hotseatItems.size(); i++) { if (hotseatItems.keyAt(i) >= mControllers.taskbarActivityContext.getDeviceProfile() .numShownHotseatIcons) { break; } if (hotseatItems.valueAt(i).getTargetPackage() .equals(runningApp.getTargetPackage())) { shouldAddOnTaskbar = false; break; } } if (shouldAddOnTaskbar) { filteredRunningApps.add(new WorkspaceItemInfo(runningApp)); } } mRunningApps = filteredRunningApps; mControllers.taskbarViewController.commitRunningAppsToUI(); } /** * Returns a copy of hotseatItems with the addition of currently running applications. */ @Override protected ItemInfo[] updateHotseatItemInfos(ItemInfo[] hotseatItemInfos) { // hotseatItemInfos.length would be 0 if deviceProfile.numShownHotseatIcons is 0, so we // don't want to show anything in the hotseat if (hotseatItemInfos.length == 0) return hotseatItemInfos; int runningAppsIndex = 0; ItemInfo[] newHotseatItemsInfo = Arrays.copyOf( hotseatItemInfos, hotseatItemInfos.length + mRunningApps.size()); for (int i = hotseatItemInfos.length; i < newHotseatItemsInfo.length; i++) { newHotseatItemsInfo[i] = mRunningApps.get(runningAppsIndex); runningAppsIndex++; } return newHotseatItemsInfo; } /** * Returns a list of running applications from the list of currently running tasks. */ private ArrayList getRunningAppsFromTasks() { ArrayList tasks = RecentsModel.INSTANCE.get(mContext).getRunningTasks(); ArrayList runningApps = new ArrayList<>(); // early return if apps is empty, since we would have no AppInfo to compare if (mApps == null) { return runningApps; } Set seenPackages = new HashSet<>(); for (ActivityManager.RunningTaskInfo taskInfo : tasks) { if (taskInfo.realActivity == null) continue; // If a different task for the same package has already been handled, skip this one String taskPackage = taskInfo.realActivity.getPackageName(); if (seenPackages.contains(taskPackage)) continue; // Otherwise, get the corresponding AppInfo and add it to the list seenPackages.add(taskPackage); AppInfo app = getAppInfo(taskInfo.realActivity); if (app == null) continue; runningApps.add(app); } return runningApps; } /** * Retrieves the corresponding AppInfo for the activity. */ private AppInfo getAppInfo(ComponentName activity) { String packageName = activity.getPackageName(); for (AppInfo app : mApps) { if (!packageName.equals(app.getTargetPackage())) { continue; } return app; } return null; } }