1782f0c9a896db58aeaa60d15f291831b8d7b4c93Sunny Goyal/*
2782f0c9a896db58aeaa60d15f291831b8d7b4c93Sunny Goyal * Copyright (C) 2017 The Android Open Source Project
3782f0c9a896db58aeaa60d15f291831b8d7b4c93Sunny Goyal *
4782f0c9a896db58aeaa60d15f291831b8d7b4c93Sunny Goyal * Licensed under the Apache License, Version 2.0 (the "License");
5782f0c9a896db58aeaa60d15f291831b8d7b4c93Sunny Goyal * you may not use this file except in compliance with the License.
6782f0c9a896db58aeaa60d15f291831b8d7b4c93Sunny Goyal * You may obtain a copy of the License at
7782f0c9a896db58aeaa60d15f291831b8d7b4c93Sunny Goyal *
8782f0c9a896db58aeaa60d15f291831b8d7b4c93Sunny Goyal *      http://www.apache.org/licenses/LICENSE-2.0
9782f0c9a896db58aeaa60d15f291831b8d7b4c93Sunny Goyal *
10782f0c9a896db58aeaa60d15f291831b8d7b4c93Sunny Goyal * Unless required by applicable law or agreed to in writing, software
11782f0c9a896db58aeaa60d15f291831b8d7b4c93Sunny Goyal * distributed under the License is distributed on an "AS IS" BASIS,
12782f0c9a896db58aeaa60d15f291831b8d7b4c93Sunny Goyal * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13782f0c9a896db58aeaa60d15f291831b8d7b4c93Sunny Goyal * See the License for the specific language governing permissions and
14782f0c9a896db58aeaa60d15f291831b8d7b4c93Sunny Goyal * limitations under the License.
15782f0c9a896db58aeaa60d15f291831b8d7b4c93Sunny Goyal */
16782f0c9a896db58aeaa60d15f291831b8d7b4c93Sunny Goyal
17782f0c9a896db58aeaa60d15f291831b8d7b4c93Sunny Goyalpackage com.android.launcher3.compat;
18782f0c9a896db58aeaa60d15f291831b8d7b4c93Sunny Goyal
19135c1be5a319b826cbe954a30132a08e3973ffb8Sunny Goyalimport android.annotation.TargetApi;
20782f0c9a896db58aeaa60d15f291831b8d7b4c93Sunny Goyalimport android.content.Context;
2122ca9ec137ec8eb70026f90591ae01af7669a3b7Sunny Goyalimport android.content.Intent;
223ff9047221820a01c6510503466f8c78b43fdc6dCharles Heimport android.content.pm.ApplicationInfo;
23782f0c9a896db58aeaa60d15f291831b8d7b4c93Sunny Goyalimport android.content.pm.LauncherActivityInfo;
24782f0c9a896db58aeaa60d15f291831b8d7b4c93Sunny Goyalimport android.content.pm.LauncherApps;
2522ca9ec137ec8eb70026f90591ae01af7669a3b7Sunny Goyalimport android.content.pm.LauncherApps.PinItemRequest;
26135c1be5a319b826cbe954a30132a08e3973ffb8Sunny Goyalimport android.content.pm.PackageManager;
27b57645fcdb87847edd216e71e3b08107027e0ed3Sunny Goyalimport android.os.Build;
2822ca9ec137ec8eb70026f90591ae01af7669a3b7Sunny Goyalimport android.os.Parcelable;
29b57645fcdb87847edd216e71e3b08107027e0ed3Sunny Goyalimport android.os.Process;
30782f0c9a896db58aeaa60d15f291831b8d7b4c93Sunny Goyalimport android.os.UserHandle;
3186222d23e28a09a7a26e7a0d4b4830ded2efb384Tony Wickhamimport android.support.annotation.Nullable;
32782f0c9a896db58aeaa60d15f291831b8d7b4c93Sunny Goyal
3322ca9ec137ec8eb70026f90591ae01af7669a3b7Sunny Goyalimport com.android.launcher3.LauncherAppState;
3422ca9ec137ec8eb70026f90591ae01af7669a3b7Sunny Goyalimport com.android.launcher3.LauncherModel;
3522ca9ec137ec8eb70026f90591ae01af7669a3b7Sunny Goyalimport com.android.launcher3.ShortcutInfo;
3686222d23e28a09a7a26e7a0d4b4830ded2efb384Tony Wickhamimport com.android.launcher3.compat.ShortcutConfigActivityInfo.ShortcutConfigActivityInfoVO;
3722ca9ec137ec8eb70026f90591ae01af7669a3b7Sunny Goyalimport com.android.launcher3.graphics.LauncherIcons;
3822ca9ec137ec8eb70026f90591ae01af7669a3b7Sunny Goyalimport com.android.launcher3.shortcuts.ShortcutInfoCompat;
3922ca9ec137ec8eb70026f90591ae01af7669a3b7Sunny Goyalimport com.android.launcher3.util.LooperExecutor;
4086222d23e28a09a7a26e7a0d4b4830ded2efb384Tony Wickhamimport com.android.launcher3.util.PackageUserKey;
4186222d23e28a09a7a26e7a0d4b4830ded2efb384Tony Wickham
42782f0c9a896db58aeaa60d15f291831b8d7b4c93Sunny Goyalimport java.util.ArrayList;
43782f0c9a896db58aeaa60d15f291831b8d7b4c93Sunny Goyalimport java.util.List;
44782f0c9a896db58aeaa60d15f291831b8d7b4c93Sunny Goyal
45135c1be5a319b826cbe954a30132a08e3973ffb8Sunny Goyal@TargetApi(26)
46782f0c9a896db58aeaa60d15f291831b8d7b4c93Sunny Goyalpublic class LauncherAppsCompatVO extends LauncherAppsCompatVL {
47782f0c9a896db58aeaa60d15f291831b8d7b4c93Sunny Goyal
48782f0c9a896db58aeaa60d15f291831b8d7b4c93Sunny Goyal    LauncherAppsCompatVO(Context context) {
49782f0c9a896db58aeaa60d15f291831b8d7b4c93Sunny Goyal        super(context);
50782f0c9a896db58aeaa60d15f291831b8d7b4c93Sunny Goyal    }
51782f0c9a896db58aeaa60d15f291831b8d7b4c93Sunny Goyal
52782f0c9a896db58aeaa60d15f291831b8d7b4c93Sunny Goyal    @Override
53ad2e91a216edae0f25bce83a2b058c81953981afSunny Goyal    public ApplicationInfo getApplicationInfo(String packageName, int flags, UserHandle user) {
54135c1be5a319b826cbe954a30132a08e3973ffb8Sunny Goyal        try {
55135c1be5a319b826cbe954a30132a08e3973ffb8Sunny Goyal            ApplicationInfo info = mLauncherApps.getApplicationInfo(packageName, flags, user);
56135c1be5a319b826cbe954a30132a08e3973ffb8Sunny Goyal            return (info.flags & ApplicationInfo.FLAG_INSTALLED) == 0 || !info.enabled
57135c1be5a319b826cbe954a30132a08e3973ffb8Sunny Goyal                    ? null : info;
58135c1be5a319b826cbe954a30132a08e3973ffb8Sunny Goyal        } catch (PackageManager.NameNotFoundException e) {
59135c1be5a319b826cbe954a30132a08e3973ffb8Sunny Goyal            return null;
60135c1be5a319b826cbe954a30132a08e3973ffb8Sunny Goyal        }
613ff9047221820a01c6510503466f8c78b43fdc6dCharles He    }
623ff9047221820a01c6510503466f8c78b43fdc6dCharles He
633ff9047221820a01c6510503466f8c78b43fdc6dCharles He    @Override
6486222d23e28a09a7a26e7a0d4b4830ded2efb384Tony Wickham    public List<ShortcutConfigActivityInfo> getCustomShortcutActivityList(
6586222d23e28a09a7a26e7a0d4b4830ded2efb384Tony Wickham            @Nullable PackageUserKey packageUser) {
66782f0c9a896db58aeaa60d15f291831b8d7b4c93Sunny Goyal        List<ShortcutConfigActivityInfo> result = new ArrayList<>();
67b57645fcdb87847edd216e71e3b08107027e0ed3Sunny Goyal        UserHandle myUser = Process.myUserHandle();
68782f0c9a896db58aeaa60d15f291831b8d7b4c93Sunny Goyal
6922ca9ec137ec8eb70026f90591ae01af7669a3b7Sunny Goyal        final List<UserHandle> users;
7022ca9ec137ec8eb70026f90591ae01af7669a3b7Sunny Goyal        final String packageName;
7122ca9ec137ec8eb70026f90591ae01af7669a3b7Sunny Goyal        if (packageUser == null) {
7222ca9ec137ec8eb70026f90591ae01af7669a3b7Sunny Goyal            users = UserManagerCompat.getInstance(mContext).getUserProfiles();
7322ca9ec137ec8eb70026f90591ae01af7669a3b7Sunny Goyal            packageName = null;
7422ca9ec137ec8eb70026f90591ae01af7669a3b7Sunny Goyal        } else {
7522ca9ec137ec8eb70026f90591ae01af7669a3b7Sunny Goyal            users = new ArrayList<>(1);
7622ca9ec137ec8eb70026f90591ae01af7669a3b7Sunny Goyal            users.add(packageUser.mUser);
7722ca9ec137ec8eb70026f90591ae01af7669a3b7Sunny Goyal            packageName = packageUser.mPackageName;
7822ca9ec137ec8eb70026f90591ae01af7669a3b7Sunny Goyal        }
7922ca9ec137ec8eb70026f90591ae01af7669a3b7Sunny Goyal        for (UserHandle user : users) {
8022ca9ec137ec8eb70026f90591ae01af7669a3b7Sunny Goyal            boolean ignoreTargetSdk = myUser.equals(user);
8122ca9ec137ec8eb70026f90591ae01af7669a3b7Sunny Goyal            List<LauncherActivityInfo> activities =
8222ca9ec137ec8eb70026f90591ae01af7669a3b7Sunny Goyal                    mLauncherApps.getShortcutConfigActivityList(packageName, user);
8322ca9ec137ec8eb70026f90591ae01af7669a3b7Sunny Goyal            for (LauncherActivityInfo activityInfo : activities) {
8422ca9ec137ec8eb70026f90591ae01af7669a3b7Sunny Goyal                if (ignoreTargetSdk || activityInfo.getApplicationInfo().targetSdkVersion >=
8522ca9ec137ec8eb70026f90591ae01af7669a3b7Sunny Goyal                        Build.VERSION_CODES.O) {
8622ca9ec137ec8eb70026f90591ae01af7669a3b7Sunny Goyal                    result.add(new ShortcutConfigActivityInfoVO(activityInfo));
87782f0c9a896db58aeaa60d15f291831b8d7b4c93Sunny Goyal                }
88782f0c9a896db58aeaa60d15f291831b8d7b4c93Sunny Goyal            }
89782f0c9a896db58aeaa60d15f291831b8d7b4c93Sunny Goyal        }
90782f0c9a896db58aeaa60d15f291831b8d7b4c93Sunny Goyal
91782f0c9a896db58aeaa60d15f291831b8d7b4c93Sunny Goyal        return result;
92782f0c9a896db58aeaa60d15f291831b8d7b4c93Sunny Goyal    }
9322ca9ec137ec8eb70026f90591ae01af7669a3b7Sunny Goyal
9422ca9ec137ec8eb70026f90591ae01af7669a3b7Sunny Goyal    /**
9522ca9ec137ec8eb70026f90591ae01af7669a3b7Sunny Goyal     * request.accept() will initiate the following flow:
9622ca9ec137ec8eb70026f90591ae01af7669a3b7Sunny Goyal     *      -> go-to-system-process for actual processing (a)
9722ca9ec137ec8eb70026f90591ae01af7669a3b7Sunny Goyal     *      -> callback-to-launcher on UI thread (b)
9822ca9ec137ec8eb70026f90591ae01af7669a3b7Sunny Goyal     *      -> post callback on the worker thread (c)
9922ca9ec137ec8eb70026f90591ae01af7669a3b7Sunny Goyal     *      -> Update model and unpin (in system) any shortcut not in out model. (d)
10022ca9ec137ec8eb70026f90591ae01af7669a3b7Sunny Goyal     *
10122ca9ec137ec8eb70026f90591ae01af7669a3b7Sunny Goyal     * Note that (b) will take at-least one frame as it involves posting callback from binder
10222ca9ec137ec8eb70026f90591ae01af7669a3b7Sunny Goyal     * thread to UI thread.
10322ca9ec137ec8eb70026f90591ae01af7669a3b7Sunny Goyal     * If (d) happens before we add this shortcut to our model, we will end up unpinning
10422ca9ec137ec8eb70026f90591ae01af7669a3b7Sunny Goyal     * the shortcut in the system.
10522ca9ec137ec8eb70026f90591ae01af7669a3b7Sunny Goyal     * Here its the caller's responsibility to add the newly created ShortcutInfo immediately
10622ca9ec137ec8eb70026f90591ae01af7669a3b7Sunny Goyal     * to the model (which may involves a single post-to-worker-thread). That will guarantee
10722ca9ec137ec8eb70026f90591ae01af7669a3b7Sunny Goyal     * that (d) happens after model is updated.
10822ca9ec137ec8eb70026f90591ae01af7669a3b7Sunny Goyal     */
10922ca9ec137ec8eb70026f90591ae01af7669a3b7Sunny Goyal    @Nullable
11022ca9ec137ec8eb70026f90591ae01af7669a3b7Sunny Goyal    public static ShortcutInfo createShortcutInfoFromPinItemRequest(
11122ca9ec137ec8eb70026f90591ae01af7669a3b7Sunny Goyal            Context context, final PinItemRequest request, final long acceptDelay) {
11222ca9ec137ec8eb70026f90591ae01af7669a3b7Sunny Goyal        if (request != null &&
11322ca9ec137ec8eb70026f90591ae01af7669a3b7Sunny Goyal                request.getRequestType() == PinItemRequest.REQUEST_TYPE_SHORTCUT &&
11422ca9ec137ec8eb70026f90591ae01af7669a3b7Sunny Goyal                request.isValid()) {
11522ca9ec137ec8eb70026f90591ae01af7669a3b7Sunny Goyal
11622ca9ec137ec8eb70026f90591ae01af7669a3b7Sunny Goyal            if (acceptDelay <= 0) {
11722ca9ec137ec8eb70026f90591ae01af7669a3b7Sunny Goyal                if (!request.accept()) {
11822ca9ec137ec8eb70026f90591ae01af7669a3b7Sunny Goyal                    return null;
11922ca9ec137ec8eb70026f90591ae01af7669a3b7Sunny Goyal                }
12022ca9ec137ec8eb70026f90591ae01af7669a3b7Sunny Goyal            } else {
12122ca9ec137ec8eb70026f90591ae01af7669a3b7Sunny Goyal                // Block the worker thread until the accept() is called.
12222ca9ec137ec8eb70026f90591ae01af7669a3b7Sunny Goyal                new LooperExecutor(LauncherModel.getWorkerLooper()).execute(new Runnable() {
12322ca9ec137ec8eb70026f90591ae01af7669a3b7Sunny Goyal                    @Override
12422ca9ec137ec8eb70026f90591ae01af7669a3b7Sunny Goyal                    public void run() {
12522ca9ec137ec8eb70026f90591ae01af7669a3b7Sunny Goyal                        try {
12622ca9ec137ec8eb70026f90591ae01af7669a3b7Sunny Goyal                            Thread.sleep(acceptDelay);
12722ca9ec137ec8eb70026f90591ae01af7669a3b7Sunny Goyal                        } catch (InterruptedException e) {
12822ca9ec137ec8eb70026f90591ae01af7669a3b7Sunny Goyal                            // Ignore
12922ca9ec137ec8eb70026f90591ae01af7669a3b7Sunny Goyal                        }
13022ca9ec137ec8eb70026f90591ae01af7669a3b7Sunny Goyal                        if (request.isValid()) {
13122ca9ec137ec8eb70026f90591ae01af7669a3b7Sunny Goyal                            request.accept();
13222ca9ec137ec8eb70026f90591ae01af7669a3b7Sunny Goyal                        }
13322ca9ec137ec8eb70026f90591ae01af7669a3b7Sunny Goyal                    }
13422ca9ec137ec8eb70026f90591ae01af7669a3b7Sunny Goyal                });
13522ca9ec137ec8eb70026f90591ae01af7669a3b7Sunny Goyal            }
13622ca9ec137ec8eb70026f90591ae01af7669a3b7Sunny Goyal
13722ca9ec137ec8eb70026f90591ae01af7669a3b7Sunny Goyal            ShortcutInfoCompat compat = new ShortcutInfoCompat(request.getShortcutInfo());
13822ca9ec137ec8eb70026f90591ae01af7669a3b7Sunny Goyal            ShortcutInfo info = new ShortcutInfo(compat, context);
13922ca9ec137ec8eb70026f90591ae01af7669a3b7Sunny Goyal            // Apply the unbadged icon and fetch the actual icon asynchronously.
14022ca9ec137ec8eb70026f90591ae01af7669a3b7Sunny Goyal            info.iconBitmap = LauncherIcons
14122ca9ec137ec8eb70026f90591ae01af7669a3b7Sunny Goyal                    .createShortcutIcon(compat, context, false /* badged */);
14222ca9ec137ec8eb70026f90591ae01af7669a3b7Sunny Goyal            LauncherAppState.getInstance(context).getModel()
14322ca9ec137ec8eb70026f90591ae01af7669a3b7Sunny Goyal                    .updateAndBindShortcutInfo(info, compat);
14422ca9ec137ec8eb70026f90591ae01af7669a3b7Sunny Goyal            return info;
14522ca9ec137ec8eb70026f90591ae01af7669a3b7Sunny Goyal        } else {
14622ca9ec137ec8eb70026f90591ae01af7669a3b7Sunny Goyal            return null;
14722ca9ec137ec8eb70026f90591ae01af7669a3b7Sunny Goyal        }
14822ca9ec137ec8eb70026f90591ae01af7669a3b7Sunny Goyal    }
14922ca9ec137ec8eb70026f90591ae01af7669a3b7Sunny Goyal
15022ca9ec137ec8eb70026f90591ae01af7669a3b7Sunny Goyal    public static PinItemRequest getPinItemRequest(Intent intent) {
15122ca9ec137ec8eb70026f90591ae01af7669a3b7Sunny Goyal        Parcelable extra = intent.getParcelableExtra(LauncherApps.EXTRA_PIN_ITEM_REQUEST);
15222ca9ec137ec8eb70026f90591ae01af7669a3b7Sunny Goyal        return extra instanceof PinItemRequest ? (PinItemRequest) extra : null;
15322ca9ec137ec8eb70026f90591ae01af7669a3b7Sunny Goyal    }
154782f0c9a896db58aeaa60d15f291831b8d7b4c93Sunny Goyal}
155