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

Commit 3b00e790 authored by Sunny Goyal's avatar Sunny Goyal Committed by Android (Google) Code Review
Browse files

Merge "Using resource override instead of code-swap for ApiWrapper" into main

parents 8ddacf21 11117d9b
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -38,6 +38,7 @@
    <string name="nav_handle_long_press_handler_class" translatable="false"></string>
    <string name="assist_utils_class" translatable="false"></string>
    <string name="assist_state_manager_class" translatable="false"></string>
    <string name="api_wrapper_class" translatable="false">com.android.launcher3.uioverrides.SystemApiWrapper</string>

    <!-- The number of thumbnails and icons to keep in the cache. The thumbnail cache size also
         determines how many thumbnails will be fetched in the background. -->
+2 −2
Original line number Diff line number Diff line
@@ -113,8 +113,8 @@ import com.android.launcher3.testing.TestLogging;
import com.android.launcher3.testing.shared.TestProtocol;
import com.android.launcher3.touch.ItemClickHandler;
import com.android.launcher3.touch.ItemClickHandler.ItemClickProxy;
import com.android.launcher3.uioverrides.ApiWrapper;
import com.android.launcher3.util.ActivityOptionsWrapper;
import com.android.launcher3.util.ApiWrapper;
import com.android.launcher3.util.ComponentKey;
import com.android.launcher3.util.DisplayController;
import com.android.launcher3.util.Executors;
@@ -1120,7 +1120,7 @@ public class TaskbarActivityContext extends BaseTaskbarContext {
                        } else if (info.isPromise()) {
                            TestLogging.recordEvent(
                                    TestProtocol.SEQUENCE_MAIN, "start: taskbarPromiseIcon");
                            intent = ApiWrapper.getAppMarketActivityIntent(this,
                            intent = ApiWrapper.INSTANCE.get(this).getAppMarketActivityIntent(
                                    info.getTargetPackage(), Process.myUserHandle());
                            startActivity(intent);

+0 −201
Original line number Diff line number Diff line
/*
 * 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.launcher3.uioverrides;

import android.app.ActivityOptions;
import android.app.PendingIntent;
import android.app.Person;
import android.content.Context;
import android.content.Intent;
import android.content.IntentSender;
import android.content.pm.ActivityInfo;
import android.content.pm.LauncherActivityInfo;
import android.content.pm.LauncherApps;
import android.content.pm.LauncherUserInfo;
import android.content.pm.ShortcutInfo;
import android.graphics.drawable.ColorDrawable;
import android.net.Uri;
import android.os.UserHandle;
import android.os.UserManager;
import android.util.ArrayMap;
import android.window.RemoteTransition;

import com.android.launcher3.Flags;
import com.android.launcher3.Utilities;
import com.android.launcher3.proxy.ProxyActivityStarter;
import com.android.launcher3.util.StartActivityParams;
import com.android.launcher3.util.UserIconInfo;
import com.android.quickstep.util.FadeOutRemoteTransition;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;

/**
 * A wrapper for the hidden API calls
 */
public class ApiWrapper {

    public static final boolean TASKBAR_DRAWN_IN_PROCESS = true;

    public static Person[] getPersons(ShortcutInfo si) {
        Person[] persons = si.getPersons();
        return persons == null ? Utilities.EMPTY_PERSON_ARRAY : persons;
    }

    public static Map<String, LauncherActivityInfo> getActivityOverrides(Context context) {
        return context.getSystemService(LauncherApps.class).getActivityOverrides();
    }

    /**
     * Creates an ActivityOptions to play fade-out animation on closing targets
     */
    public static ActivityOptions createFadeOutAnimOptions(Context context) {
        ActivityOptions options = ActivityOptions.makeBasic();
        options.setRemoteTransition(new RemoteTransition(new FadeOutRemoteTransition()));
        return options;
    }

    /**
     * Returns a map of all users on the device to their corresponding UI properties
     */
    public static Map<UserHandle, UserIconInfo> queryAllUsers(Context context) {
        UserManager um = context.getSystemService(UserManager.class);
        Map<UserHandle, UserIconInfo> users = new ArrayMap<>();
        List<UserHandle> usersActual = um.getUserProfiles();
        if (usersActual != null) {
            for (UserHandle user : usersActual) {
                if (android.os.Flags.allowPrivateProfile() && Flags.enablePrivateSpace()) {
                    LauncherApps launcherApps = context.getSystemService(LauncherApps.class);
                    LauncherUserInfo launcherUserInfo = launcherApps.getLauncherUserInfo(user);
                    if (launcherUserInfo == null) {
                        continue;
                    }
                    // UserTypes not supported in Launcher are deemed to be the current
                    // Foreground User.
                    int userType = switch (launcherUserInfo.getUserType()) {
                        case UserManager.USER_TYPE_PROFILE_MANAGED -> UserIconInfo.TYPE_WORK;
                        case UserManager.USER_TYPE_PROFILE_CLONE -> UserIconInfo.TYPE_CLONED;
                        case UserManager.USER_TYPE_PROFILE_PRIVATE -> UserIconInfo.TYPE_PRIVATE;
                        default -> UserIconInfo.TYPE_MAIN;
                    };
                    long serial = launcherUserInfo.getUserSerialNumber();
                    users.put(user, new UserIconInfo(user, userType, serial));
                } else {
                    long serial = um.getSerialNumberForUser(user);

                    // Simple check to check if the provided user is work profile
                    // TODO: Migrate to a better platform API
                    NoopDrawable d = new NoopDrawable();
                    boolean isWork = (d != context.getPackageManager().getUserBadgedIcon(d, user));
                    UserIconInfo info = new UserIconInfo(
                            user,
                            isWork ? UserIconInfo.TYPE_WORK : UserIconInfo.TYPE_MAIN,
                            serial);
                    users.put(user, info);
                }
            }
        }
        return users;
    }

    /**
     * Returns the list of the system packages that are installed at user creation.
     * An empty list denotes that all system packages are installed for that user at creation.
     */
    public static List<String> getPreInstalledSystemPackages(Context context, UserHandle user) {
        LauncherApps launcherApps = context.getSystemService(LauncherApps.class);
        if (android.os.Flags.allowPrivateProfile() && Flags.enablePrivateSpace()
                && Flags.privateSpaceSysAppsSeparation()) {
            return launcherApps.getPreInstalledSystemPackages(user);
        } else {
            return new ArrayList<>();
        }
    }

    /**
     * Returns an intent which can be used to start the App Market activity (Installer
     * Activity).
     */
    public static Intent getAppMarketActivityIntent(Context context, String packageName,
            UserHandle user) {
        LauncherApps launcherApps = context.getSystemService(LauncherApps.class);
        if (android.os.Flags.allowPrivateProfile()
                && Flags.enablePrivateSpace()
                && (Flags.privateSpaceAppInstallerButton()
                        || Flags.enablePrivateSpaceInstallShortcut())) {
            StartActivityParams params = new StartActivityParams((PendingIntent) null, 0);
            params.intentSender = launcherApps.getAppMarketActivityIntent(packageName, user);
            ActivityOptions options = ActivityOptions.makeBasic()
                    .setPendingIntentBackgroundActivityStartMode(ActivityOptions
                            .MODE_BACKGROUND_ACTIVITY_START_ALLOWED);
            params.options = options.toBundle();
            params.requireActivityResult = false;
            return ProxyActivityStarter.getLaunchIntent(context, params);
        } else {
            return new Intent(Intent.ACTION_VIEW)
                    .setData(new Uri.Builder()
                            .scheme("market")
                            .authority("details")
                            .appendQueryParameter("id", packageName)
                            .build())
                    .putExtra(Intent.EXTRA_REFERRER, new Uri.Builder().scheme("android-app")
                            .authority(context.getPackageName()).build());
        }
    }

    /**
     * Returns an intent which can be used to open Private Space Settings.
     */
    public static Intent getPrivateSpaceSettingsIntent(Context context) {
        if (android.os.Flags.allowPrivateProfile() && Flags.enablePrivateSpace()) {
            LauncherApps launcherApps = context.getSystemService(LauncherApps.class);
            IntentSender intentSender = launcherApps.getPrivateSpaceSettingsIntent();
            if (intentSender == null) {
                return null;
            }
            StartActivityParams params = new StartActivityParams((PendingIntent) null, 0);
            params.intentSender = intentSender;
            ActivityOptions options = ActivityOptions.makeBasic()
                    .setPendingIntentBackgroundActivityStartMode(ActivityOptions
                            .MODE_BACKGROUND_ACTIVITY_START_ALLOWED);
            params.options = options.toBundle();
            params.requireActivityResult = false;
            return ProxyActivityStarter.getLaunchIntent(context, params);
        }
        return null;
    }

    /**
     * Checks if an activity is flagged as non-resizeable.
     */
    public static boolean isNonResizeableActivity(LauncherActivityInfo lai) {
        return lai.getActivityInfo().resizeMode == ActivityInfo.RESIZE_MODE_UNRESIZEABLE;
    }

    private static class NoopDrawable extends ColorDrawable {
        @Override
        public int getIntrinsicHeight() {
            return 1;
        }

        @Override
        public int getIntrinsicWidth() {
            return 1;
        }
    }
}
+133 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2024 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.uioverrides

import android.app.ActivityOptions
import android.app.PendingIntent
import android.content.Context
import android.content.Intent
import android.content.pm.ActivityInfo
import android.content.pm.LauncherActivityInfo
import android.content.pm.LauncherApps
import android.content.pm.ShortcutInfo
import android.os.Flags.allowPrivateProfile
import android.os.UserHandle
import android.os.UserManager
import android.util.ArrayMap
import android.window.RemoteTransition
import com.android.launcher3.Flags.enablePrivateSpace
import com.android.launcher3.Flags.enablePrivateSpaceInstallShortcut
import com.android.launcher3.Flags.privateSpaceAppInstallerButton
import com.android.launcher3.Flags.privateSpaceSysAppsSeparation
import com.android.launcher3.Utilities
import com.android.launcher3.proxy.ProxyActivityStarter
import com.android.launcher3.util.ApiWrapper
import com.android.launcher3.util.StartActivityParams
import com.android.launcher3.util.UserIconInfo
import com.android.quickstep.util.FadeOutRemoteTransition

/** A wrapper for the hidden API calls */
class SystemApiWrapper(context: Context?) : ApiWrapper(context) {

    override fun getPersons(si: ShortcutInfo) = si.persons ?: Utilities.EMPTY_PERSON_ARRAY

    override fun getActivityOverrides(): Map<String, LauncherActivityInfo> =
        mContext.getSystemService(LauncherApps::class.java)!!.activityOverrides

    override fun createFadeOutAnimOptions(): ActivityOptions =
        ActivityOptions.makeBasic().apply {
            remoteTransition = RemoteTransition(FadeOutRemoteTransition())
        }

    override fun queryAllUsers(): Map<UserHandle, UserIconInfo> {
        if (!allowPrivateProfile() || !enablePrivateSpace()) {
            return super.queryAllUsers()
        }
        val users = ArrayMap<UserHandle, UserIconInfo>()
        mContext.getSystemService(UserManager::class.java)!!.userProfiles?.forEach { user ->
            mContext.getSystemService(LauncherApps::class.java)!!.getLauncherUserInfo(user)?.apply {
                users[user] =
                    UserIconInfo(
                        user,
                        when (userType) {
                            UserManager.USER_TYPE_PROFILE_MANAGED -> UserIconInfo.TYPE_WORK
                            UserManager.USER_TYPE_PROFILE_CLONE -> UserIconInfo.TYPE_CLONED
                            UserManager.USER_TYPE_PROFILE_PRIVATE -> UserIconInfo.TYPE_PRIVATE
                            else -> UserIconInfo.TYPE_MAIN
                        },
                        userSerialNumber.toLong()
                    )
            }
        }
        return users
    }

    override fun getPreInstalledSystemPackages(user: UserHandle): List<String> =
        if (allowPrivateProfile() && enablePrivateSpace() && privateSpaceSysAppsSeparation())
            mContext
                .getSystemService(LauncherApps::class.java)!!
                .getPreInstalledSystemPackages(user)
        else ArrayList()

    override fun getAppMarketActivityIntent(packageName: String, user: UserHandle): Intent =
        if (
            allowPrivateProfile() &&
                enablePrivateSpace() &&
                (privateSpaceAppInstallerButton() || enablePrivateSpaceInstallShortcut())
        )
            ProxyActivityStarter.getLaunchIntent(
                mContext,
                StartActivityParams(null as PendingIntent?, 0).apply {
                    intentSender =
                        mContext
                            .getSystemService(LauncherApps::class.java)!!
                            .getAppMarketActivityIntent(packageName, user)
                    options =
                        ActivityOptions.makeBasic()
                            .setPendingIntentBackgroundActivityStartMode(
                                ActivityOptions.MODE_BACKGROUND_ACTIVITY_START_ALLOWED
                            )
                            .toBundle()
                    requireActivityResult = false
                }
            )
        else super.getAppMarketActivityIntent(packageName, user)

    /** Returns an intent which can be used to open Private Space Settings. */
    override fun getPrivateSpaceSettingsIntent(): Intent? =
        if (allowPrivateProfile() && enablePrivateSpace())
            ProxyActivityStarter.getLaunchIntent(
                mContext,
                StartActivityParams(null as PendingIntent?, 0).apply {
                    intentSender =
                        mContext
                            .getSystemService(LauncherApps::class.java)
                            ?.privateSpaceSettingsIntent
                            ?: return null
                    options =
                        ActivityOptions.makeBasic()
                            .setPendingIntentBackgroundActivityStartMode(
                                ActivityOptions.MODE_BACKGROUND_ACTIVITY_START_ALLOWED
                            )
                            .toBundle()
                    requireActivityResult = false
                }
            )
        else null

    override fun isNonResizeableActivity(lai: LauncherActivityInfo) =
        lai.activityInfo.resizeMode == ActivityInfo.RESIZE_MODE_UNRESIZEABLE
}
+1 −0
Original line number Diff line number Diff line
@@ -78,6 +78,7 @@
    <string name="launcher_restore_event_logger_class" translatable="false"></string>
    <!--  Used for determining category of a widget presented in widget recommendations. -->
    <string name="widget_recommendation_category_provider_class" translatable="false"></string>
    <string name="api_wrapper_class" translatable="false"></string>

    <!-- Default packages -->
    <string name="wallpaper_picker_package" translatable="false"></string>
Loading