Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 0eaf9ebd authored by Gustav Sennton's avatar Gustav Sennton
Browse files

Remove references to FEATURE_PC and related Desktop classes in Launcher

Also clean up TaskbarRecentAppsController APIs

Flag: NA
Test: DesktopTaskbarRunningAppsControllerTest
Bug: 330551930
Change-Id: Ibd9c3d6aa1d5423b51a48ed0a972196752d5199a
parent 43f65905
Loading
Loading
Loading
Loading
+0 −88
Original line number Diff line number Diff line
/*
 * 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 static com.android.launcher3.taskbar.TaskbarNavButtonController.BUTTON_NOTIFICATIONS;
import static com.android.launcher3.taskbar.TaskbarNavButtonController.BUTTON_QUICK_SETTINGS;

import android.content.Context;
import android.content.pm.ActivityInfo.Config;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.FrameLayout;

import androidx.annotation.Nullable;

import com.android.launcher3.R;
import com.android.launcher3.taskbar.navbutton.NearestTouchFrame;

/**
 * Controller for managing buttons and status icons in taskbar in a desktop environment.
 */
public class DesktopNavbarButtonsViewController extends NavbarButtonsViewController {

    private final TaskbarActivityContext mContext;
    private final FrameLayout mNavButtonsView;
    private final ViewGroup mNavButtonContainer;
    private final ViewGroup mStartContextualContainer;
    private final View mAllAppsButton;

    private TaskbarControllers mControllers;

    public DesktopNavbarButtonsViewController(TaskbarActivityContext context,
            @Nullable Context navigationBarPanelContext, NearestTouchFrame navButtonsView) {
        super(context, navigationBarPanelContext, navButtonsView);
        mContext = context;
        mNavButtonsView = navButtonsView;
        mNavButtonContainer = mNavButtonsView.findViewById(R.id.end_nav_buttons);
        mStartContextualContainer = mNavButtonsView.findViewById(R.id.start_contextual_buttons);
        mAllAppsButton = LayoutInflater.from(context)
                .inflate(R.layout.taskbar_all_apps_button, mStartContextualContainer, false);
        mAllAppsButton.setOnClickListener(v -> mControllers.taskbarAllAppsController.toggle());
    }

    /**
     * Initializes the controller
     */
    @Override
    public void init(TaskbarControllers controllers) {
        mControllers = controllers;
        super.init(controllers);
    }

    @Override
    protected void setupController() {
        mNavButtonsView.getLayoutParams().height = mContext.getDeviceProfile().taskbarHeight;

        // Quick settings and notifications buttons
        addButton(R.drawable.ic_sysbar_quick_settings, BUTTON_QUICK_SETTINGS,
                mNavButtonContainer, mControllers.navButtonController,
                R.id.quick_settings_button);
        addButton(R.drawable.ic_sysbar_notifications, BUTTON_NOTIFICATIONS,
                mNavButtonContainer, mControllers.navButtonController,
                R.id.notifications_button);
        // All apps button
        mStartContextualContainer.addView(mAllAppsButton);
    }

    /** Cleans up on destroy */
    @Override
    public void onDestroy() { }

    @Override
    public void onConfigurationChanged(@Config int configChanges) { }
}
+0 −153
Original line number Diff line number Diff line
/*
 * 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<ItemInfo> 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<ItemInfo> hotseatItems) {
        ArrayList<AppInfo> runningApps = getRunningAppsFromTasks();
        ArrayList<ItemInfo> 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<AppInfo> getRunningAppsFromTasks() {
        ArrayList<ActivityManager.RunningTaskInfo> tasks =
                RecentsModel.INSTANCE.get(mContext).getRunningTasks();
        ArrayList<AppInfo> runningApps = new ArrayList<>();
        // early return if apps is empty, since we would have no AppInfo to compare
        if (mApps == null)  {
            return runningApps;
        }

        Set<String> 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;
    }
}
+11 −14
Original line number Diff line number Diff line
@@ -45,7 +45,6 @@ class DesktopTaskbarRunningAppsController(

    private var apps: Array<AppInfo>? = null
    private var allRunningDesktopAppInfos: List<AppInfo>? = null
    private var runningDesktopAppInfosExceptHotseatItems: List<ItemInfo>? = null

    private val isInDesktopMode: Boolean
        get() = desktopVisibilityController?.areDesktopTasksVisible() ?: false
@@ -63,20 +62,24 @@ class DesktopTaskbarRunningAppsController(
    override fun isEnabled() = true

    @VisibleForTesting
    public override fun updateHotseatItemInfos(hotseatItems: Array<ItemInfo>?): Array<ItemInfo>? {
        val actualHotseatItems = hotseatItems ?: return super.updateHotseatItemInfos(null)
    public override fun updateHotseatItemInfos(hotseatItems: Array<ItemInfo?>): Array<ItemInfo?> {
        if (!isInDesktopMode) {
            Log.d(TAG, "updateHotseatItemInfos: not in Desktop Mode")
            return hotseatItems
        }
        val newHotseatItemInfos =
            actualHotseatItems
            hotseatItems
                .filterNotNull()
                // Ignore predicted apps - we show running apps instead
                .filter { itemInfo -> !itemInfo.isPredictedItem }
                .toMutableList()
        val runningDesktopAppInfos =
            runningDesktopAppInfosExceptHotseatItems ?: return newHotseatItemInfos.toTypedArray()
            allRunningDesktopAppInfos?.let {
                getRunningDesktopAppInfosExceptHotseatApps(it, newHotseatItemInfos.toList())
            }
        if (runningDesktopAppInfos != null) {
            newHotseatItemInfos.addAll(runningDesktopAppInfos)
        }
        return newHotseatItemInfos.toTypedArray()
    }

@@ -88,19 +91,13 @@ class DesktopTaskbarRunningAppsController(
    }

    @VisibleForTesting
    public override fun updateRunningApps(hotseatItems: SparseArray<ItemInfo>?) {
    public override fun updateRunningApps() {
        if (!isInDesktopMode) {
            Log.d(TAG, "updateRunningApps: not in Desktop Mode")
            mControllers.taskbarViewController.commitRunningAppsToUI()
            return
        }
        val allRunningDesktopAppInfos = getRunningDesktopAppInfos()
        this.allRunningDesktopAppInfos = allRunningDesktopAppInfos
        runningDesktopAppInfosExceptHotseatItems =
            hotseatItems?.let {
                getRunningDesktopAppInfosExceptHotseatApps(allRunningDesktopAppInfos, it.toList())
            }

        allRunningDesktopAppInfos = getRunningDesktopAppInfos()
        mControllers.taskbarViewController.commitRunningAppsToUI()
    }

+0 −62
Original line number Diff line number Diff line
/*
 * Copyright (C) 2021 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 androidx.annotation.Nullable;

import com.android.launcher3.uioverrides.QuickstepLauncher;
import com.android.quickstep.util.TISBindHelper;

/**
 * A data source which integrates with a Launcher instance, used specifically for a
 * desktop environment.
 */
public class DesktopTaskbarUIController extends TaskbarUIController {

    private final QuickstepLauncher mLauncher;

    public DesktopTaskbarUIController(QuickstepLauncher launcher) {
        mLauncher = launcher;
    }

    @SuppressWarnings("MissingSuperCall") // TODO: Fix me
    @Override
    protected void init(TaskbarControllers taskbarControllers) {
        super.init(taskbarControllers);
        mLauncher.getHotseat().setIconsAlpha(0f);
        mControllers.taskbarViewController.updateRunningApps();
    }

    @SuppressWarnings("MissingSuperCall") // TODO: Fix me
    @Override
    protected void onDestroy() {
        super.onDestroy();
        mLauncher.getHotseat().setIconsAlpha(1f);
    }

    /** Disable taskbar stashing in desktop environment. */
    @Override
    public boolean supportsVisualStashing() {
        return false;
    }

    @Nullable
    @Override
    protected TISBindHelper getTISBindHelper() {
        return mLauncher.getTISBindHelper();
    }
}
+9 −18
Original line number Diff line number Diff line
@@ -15,7 +15,6 @@
 */
package com.android.launcher3.taskbar;

import static android.content.pm.PackageManager.FEATURE_PC;
import static android.os.Trace.TRACE_TAG_APP;
import static android.view.Display.DEFAULT_DISPLAY;
import static android.view.ViewGroup.LayoutParams.MATCH_PARENT;
@@ -248,8 +247,6 @@ public class TaskbarActivityContext extends BaseTaskbarContext {

        mAccessibilityDelegate = new TaskbarShortcutMenuAccessibilityDelegate(this);

        final boolean isPcMode = getPackageManager().hasSystemFeature(FEATURE_PC);

        // If Bubble bar is present, TaskbarControllers depends on it so build it first.
        Optional<BubbleControllers> bubbleControllersOptional = Optional.empty();
        BubbleBarController.onTaskbarRecreated();
@@ -280,11 +277,7 @@ public class TaskbarActivityContext extends BaseTaskbarContext {
        mControllers = new TaskbarControllers(this,
                new TaskbarDragController(this),
                buttonController,
                isPcMode
                        ? new DesktopNavbarButtonsViewController(this, mNavigationBarPanelContext,
                                navButtonsView)
                        : new NavbarButtonsViewController(this, mNavigationBarPanelContext,
                                navButtonsView),
                new NavbarButtonsViewController(this, mNavigationBarPanelContext, navButtonsView),
                rotationButtonController,
                new TaskbarDragLayerController(this, mDragLayer),
                new TaskbarViewController(this, taskbarView),
@@ -305,7 +298,7 @@ public class TaskbarActivityContext extends BaseTaskbarContext {
                new VoiceInteractionWindowController(this),
                new TaskbarTranslationController(this),
                new TaskbarSpringOnStashController(this),
                createTaskbarRecentAppsController(isPcMode),
                createTaskbarRecentAppsController(),
                TaskbarEduTooltipController.newInstance(this),
                new KeyboardQuickSwitchController(),
                new TaskbarPinningController(this),
@@ -314,16 +307,14 @@ public class TaskbarActivityContext extends BaseTaskbarContext {
        mLauncherPrefs = LauncherPrefs.get(this);
    }

    private TaskbarRecentAppsController createTaskbarRecentAppsController(boolean isPcMode) {
        if (isPcMode) return new DesktopTaskbarRecentAppsController(this);
    private TaskbarRecentAppsController createTaskbarRecentAppsController() {
        // TODO(b/335401172): unify DesktopMode checks in Launcher
        final boolean showRunningAppsInDesktopMode = enableDesktopWindowingMode()
                && enableDesktopWindowingTaskbarRunningApps();
        return showRunningAppsInDesktopMode
                        ? new DesktopTaskbarRunningAppsController(
        if (enableDesktopWindowingMode() && enableDesktopWindowingTaskbarRunningApps()) {
            return new DesktopTaskbarRunningAppsController(
                    RecentsModel.INSTANCE.get(this),
                                LauncherActivityInterface.INSTANCE.getDesktopVisibilityController())
                        : TaskbarRecentAppsController.DEFAULT;
                    LauncherActivityInterface.INSTANCE.getDesktopVisibilityController());
        }
        return TaskbarRecentAppsController.DEFAULT;
    }

    /** Updates {@link DeviceProfile} instances for any Taskbar windows. */
Loading