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

Commit ac70b037 authored by Riddle Hsu's avatar Riddle Hsu
Browse files

Reduce unnecessary query of checking home package

Currently while desktop mode is enabled, each transition will
always invoke home package condition 4 times. The total time of
the binder transactions to package manager could take about 5ms,
that delays the transition play time.

This change caches the package name and updates it when the default
home is changed. So most of the time there is no need to query again.

This lets caller set a supplier if needed. Such as launcher could
consider to use its existing observer:
  OverviewComponentObserver.INSTANCE.get(context)
     .getHomeIntent().getPackage();

Bug: 365023423
Test: Not showing app handle when launching widget settings
Flag: EXEMPT bugfix
Change-Id: I4e8d72b84c384fc4e00c1f681422d13b3ed201c2
parent 759f9ccc
Loading
Loading
Loading
Loading
+4 −1
Original line number Diff line number Diff line
@@ -23,6 +23,7 @@ import android.content.pm.PackageManager
import android.window.DesktopModeFlags
import com.android.internal.R
import com.android.internal.policy.DesktopModeCompatUtils
import java.util.function.Supplier

/**
 * Class to decide whether to apply app compat policies in desktop mode.
@@ -34,9 +35,11 @@ class DesktopModeCompatPolicy(private val context: Context) {
    private val pkgManager: PackageManager
        get() = context.getPackageManager()
    private val defaultHomePackage: String?
        get() = pkgManager.getHomeActivities(ArrayList())?.packageName
        get() = defaultHomePackageSupplier?.get()
            ?: pkgManager.getHomeActivities(ArrayList())?.packageName
    private val packageInfoCache = mutableMapOf<String, Boolean>()

    var defaultHomePackageSupplier: Supplier<String?>? = null

    /**
     * If the top activity should be exempt from desktop windowing and forced back to fullscreen.
+9 −2
Original line number Diff line number Diff line
@@ -95,6 +95,7 @@ import com.android.wm.shell.compatui.impl.DefaultComponentIdGenerator;
import com.android.wm.shell.desktopmode.DesktopMode;
import com.android.wm.shell.desktopmode.DesktopTasksController;
import com.android.wm.shell.desktopmode.DesktopUserRepositories;
import com.android.wm.shell.desktopmode.common.DefaultHomePackageSupplier;
import com.android.wm.shell.desktopmode.desktopwallpaperactivity.DesktopWallpaperActivityTokenProvider;
import com.android.wm.shell.displayareahelper.DisplayAreaHelper;
import com.android.wm.shell.displayareahelper.DisplayAreaHelperController;
@@ -260,8 +261,14 @@ public abstract class WMShellBaseModule {

    @WMSingleton
    @Provides
    static DesktopModeCompatPolicy provideDesktopModeCompatPolicy(Context context) {
        return new DesktopModeCompatPolicy(context);
    static DesktopModeCompatPolicy provideDesktopModeCompatPolicy(
            Context context,
            ShellInit shellInit,
            @ShellMainThread Handler mainHandler) {
        final DesktopModeCompatPolicy policy = new DesktopModeCompatPolicy(context);
        policy.setDefaultHomePackageSupplier(new DefaultHomePackageSupplier(
                context, shellInit, mainHandler));
        return policy;
    }

    @WMSingleton
+65 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2025 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.wm.shell.desktopmode.common

import android.content.BroadcastReceiver
import android.content.Context
import android.content.Intent
import android.content.IntentFilter
import android.os.Handler
import com.android.wm.shell.shared.annotations.ShellMainThread
import com.android.wm.shell.sysui.ShellInit
import java.util.function.Supplier

/**
 * This supplies the package name of default home in an efficient way. The query to package manager
 * only executes on initialization and when the preferred activity (e.g. default home) is changed.
 */
class DefaultHomePackageSupplier(
    private val context: Context,
    shellInit: ShellInit,
    @ShellMainThread private val mainHandler: Handler,
) : BroadcastReceiver(), Supplier<String?> {

    private var defaultHomePackage: String? = null

    init {
        shellInit.addInitCallback({ onInit() }, this)
    }

    private fun onInit() {
        context.registerReceiver(
            this,
            IntentFilter(Intent.ACTION_PREFERRED_ACTIVITY_CHANGED),
            null /* broadcastPermission */,
            mainHandler,
        )
    }

    private fun updateDefaultHomePackage(): String? {
        defaultHomePackage = context.packageManager.getHomeActivities(ArrayList())?.packageName
        return defaultHomePackage
    }

    override fun onReceive(contxt: Context?, intent: Intent?) {
        updateDefaultHomePackage()
    }

    override fun get(): String? {
        return defaultHomePackage ?: updateDefaultHomePackage()
    }
}