131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project/*
231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project * Copyright (C) 2008 The Android Open Source Project
331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project *
431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project * Licensed under the Apache License, Version 2.0 (the "License");
531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project * you may not use this file except in compliance with the License.
631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project * You may obtain a copy of the License at
731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project *
831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project *      http://www.apache.org/licenses/LICENSE-2.0
931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project *
1031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project * Unless required by applicable law or agreed to in writing, software
1131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS,
1231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project * See the License for the specific language governing permissions and
1431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project * limitations under the License.
1531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project */
1631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
17325dc23624160689e59fbac708cf6f222b20d025Daniel Sandlerpackage com.android.launcher3;
1831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
1931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Projectimport android.content.BroadcastReceiver;
2031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Projectimport android.content.Context;
2131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Projectimport android.content.Intent;
22f0c6ae0e35d3e020db55b5b826955da66b14b7f6Winson Chungimport android.content.SharedPreferences;
23c3a747ac245d6175a6838230d8b01c618555e062Winson Chungimport android.content.pm.ActivityInfo;
24c3a747ac245d6175a6838230d8b01c618555e062Winson Chungimport android.content.pm.PackageManager;
250b037789662d1c16627dc5b509d1ac55bc76971bSunny Goyalimport android.content.pm.ResolveInfo;
2648c7a93eb7ef15ef551aee80c179b8e7e0d2399aMichael Jurkaimport android.graphics.Bitmap;
2748c7a93eb7ef15ef551aee80c179b8e7e0d2399aMichael Jurkaimport android.graphics.BitmapFactory;
28dff0bfeb901e767ca9b57f9b8051c7fd077626e9Nilesh Agrawalimport android.text.TextUtils;
2948c7a93eb7ef15ef551aee80c179b8e7e0d2399aMichael Jurkaimport android.util.Base64;
3048c7a93eb7ef15ef551aee80c179b8e7e0d2399aMichael Jurkaimport android.util.Log;
3131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
32e0f58d73646871497596fb8f7321d407e7565c28Sunny Goyalimport com.android.launcher3.compat.LauncherActivityInfoCompat;
33e0f58d73646871497596fb8f7321d407e7565c28Sunny Goyalimport com.android.launcher3.compat.LauncherAppsCompat;
34a28b78e8385f0f590b144038157afc7d34cd48b7Adam Cohenimport com.android.launcher3.compat.UserHandleCompat;
35e0f58d73646871497596fb8f7321d407e7565c28Sunny Goyalimport com.android.launcher3.compat.UserManagerCompat;
36091440a9cb9d4f42406631004aa484cbb79214caAdam Cohenimport com.android.launcher3.util.Thunk;
37a28b78e8385f0f590b144038157afc7d34cd48b7Adam Cohen
38e0f58d73646871497596fb8f7321d407e7565c28Sunny Goyalimport org.json.JSONException;
3934c2e6cf7af328aba25c98158161dbad15ae986dMichael Jurkaimport org.json.JSONObject;
4034c2e6cf7af328aba25c98158161dbad15ae986dMichael Jurkaimport org.json.JSONStringer;
4134c2e6cf7af328aba25c98158161dbad15ae986dMichael Jurkaimport org.json.JSONTokener;
4234c2e6cf7af328aba25c98158161dbad15ae986dMichael Jurka
43e0f58d73646871497596fb8f7321d407e7565c28Sunny Goyalimport java.net.URISyntaxException;
44e428e292c27e650ab4de76b78728ba55019cd282Winson Chungimport java.util.ArrayList;
45f0c6ae0e35d3e020db55b5b826955da66b14b7f6Winson Chungimport java.util.HashSet;
46f561bdf68dd304e1d7c3f7796621a4cc39ca15f2Winson Chungimport java.util.Iterator;
47f0c6ae0e35d3e020db55b5b826955da66b14b7f6Winson Chungimport java.util.Set;
48e428e292c27e650ab4de76b78728ba55019cd282Winson Chung
4931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Projectpublic class InstallShortcutReceiver extends BroadcastReceiver {
504e871a217b286775dc6c07feb6d9f1d7a7e914beBjorn Bringert    private static final String TAG = "InstallShortcutReceiver";
514e871a217b286775dc6c07feb6d9f1d7a7e914beBjorn Bringert    private static final boolean DBG = false;
524e871a217b286775dc6c07feb6d9f1d7a7e914beBjorn Bringert
532350bc97851eea1662eee43d61290eb7a8382021Sunny Goyal    private static final String ACTION_INSTALL_SHORTCUT =
5494d6768c65929efa21bb893fdef7f269d65da3c3Winson Chung            "com.android.launcher.action.INSTALL_SHORTCUT";
55f0c6ae0e35d3e020db55b5b826955da66b14b7f6Winson Chung
562350bc97851eea1662eee43d61290eb7a8382021Sunny Goyal    private static final String LAUNCH_INTENT_KEY = "intent.launch";
572350bc97851eea1662eee43d61290eb7a8382021Sunny Goyal    private static final String NAME_KEY = "name";
582350bc97851eea1662eee43d61290eb7a8382021Sunny Goyal    private static final String ICON_KEY = "icon";
592350bc97851eea1662eee43d61290eb7a8382021Sunny Goyal    private static final String ICON_RESOURCE_NAME_KEY = "iconResource";
602350bc97851eea1662eee43d61290eb7a8382021Sunny Goyal    private static final String ICON_RESOURCE_PACKAGE_NAME_KEY = "iconResourcePackage";
61e0f58d73646871497596fb8f7321d407e7565c28Sunny Goyal
62e0f58d73646871497596fb8f7321d407e7565c28Sunny Goyal    private static final String APP_SHORTCUT_TYPE_KEY = "isAppShortcut";
63e0f58d73646871497596fb8f7321d407e7565c28Sunny Goyal    private static final String USER_HANDLE_KEY = "userHandle";
64e0f58d73646871497596fb8f7321d407e7565c28Sunny Goyal
6548c7a93eb7ef15ef551aee80c179b8e7e0d2399aMichael Jurka    // The set of shortcuts that are pending install
662350bc97851eea1662eee43d61290eb7a8382021Sunny Goyal    private static final String APPS_PENDING_INSTALL = "apps_to_install";
6748c7a93eb7ef15ef551aee80c179b8e7e0d2399aMichael Jurka
68f0c6ae0e35d3e020db55b5b826955da66b14b7f6Winson Chung    public static final int NEW_SHORTCUT_BOUNCE_DURATION = 450;
69997a92348a6d6e061737399321393449c16cd4d8Winson Chung    public static final int NEW_SHORTCUT_STAGGER_DELAY = 85;
70f0c6ae0e35d3e020db55b5b826955da66b14b7f6Winson Chung
71e0f58d73646871497596fb8f7321d407e7565c28Sunny Goyal    private static final Object sLock = new Object();
7248c7a93eb7ef15ef551aee80c179b8e7e0d2399aMichael Jurka
7348c7a93eb7ef15ef551aee80c179b8e7e0d2399aMichael Jurka    private static void addToInstallQueue(
7448c7a93eb7ef15ef551aee80c179b8e7e0d2399aMichael Jurka            SharedPreferences sharedPrefs, PendingInstallShortcutInfo info) {
7548c7a93eb7ef15ef551aee80c179b8e7e0d2399aMichael Jurka        synchronized(sLock) {
76e0f58d73646871497596fb8f7321d407e7565c28Sunny Goyal            String encoded = info.encodeToString();
77e0f58d73646871497596fb8f7321d407e7565c28Sunny Goyal            if (encoded != null) {
78e0f58d73646871497596fb8f7321d407e7565c28Sunny Goyal                Set<String> strings = sharedPrefs.getStringSet(APPS_PENDING_INSTALL, null);
79e0f58d73646871497596fb8f7321d407e7565c28Sunny Goyal                if (strings == null) {
80e0f58d73646871497596fb8f7321d407e7565c28Sunny Goyal                    strings = new HashSet<String>(1);
81e0f58d73646871497596fb8f7321d407e7565c28Sunny Goyal                } else {
82e0f58d73646871497596fb8f7321d407e7565c28Sunny Goyal                    strings = new HashSet<String>(strings);
8348c7a93eb7ef15ef551aee80c179b8e7e0d2399aMichael Jurka                }
84e0f58d73646871497596fb8f7321d407e7565c28Sunny Goyal                strings.add(encoded);
85d80439875557e8c94052e5b0f0327b656370b5fdSunny Goyal                sharedPrefs.edit().putStringSet(APPS_PENDING_INSTALL, strings).apply();
8648c7a93eb7ef15ef551aee80c179b8e7e0d2399aMichael Jurka            }
8748c7a93eb7ef15ef551aee80c179b8e7e0d2399aMichael Jurka        }
8848c7a93eb7ef15ef551aee80c179b8e7e0d2399aMichael Jurka    }
8948c7a93eb7ef15ef551aee80c179b8e7e0d2399aMichael Jurka
9097909124a2d8b89135a5885c52226191e30291b6Sunny Goyal    public static void removeFromInstallQueue(Context context, HashSet<String> packageNames,
91e0f58d73646871497596fb8f7321d407e7565c28Sunny Goyal            UserHandleCompat user) {
92df95eb12a4d288ffa143a0c3db60e7e98f3e03b9Winson Chung        if (packageNames.isEmpty()) {
93df95eb12a4d288ffa143a0c3db60e7e98f3e03b9Winson Chung            return;
94df95eb12a4d288ffa143a0c3db60e7e98f3e03b9Winson Chung        }
95f725824fa2091cab44cf1bcbfe5b5b8d06475560Sunny Goyal        SharedPreferences sp = Utilities.getPrefs(context);
96780fe59a7af8b12fbdcd7f6841edaa7f2c2e019dWinson Chung        synchronized(sLock) {
97e0f58d73646871497596fb8f7321d407e7565c28Sunny Goyal            Set<String> strings = sp.getStringSet(APPS_PENDING_INSTALL, null);
984e871a217b286775dc6c07feb6d9f1d7a7e914beBjorn Bringert            if (DBG) {
994e871a217b286775dc6c07feb6d9f1d7a7e914beBjorn Bringert                Log.d(TAG, "APPS_PENDING_INSTALL: " + strings
1004e871a217b286775dc6c07feb6d9f1d7a7e914beBjorn Bringert                        + ", removing packages: " + packageNames);
1014e871a217b286775dc6c07feb6d9f1d7a7e914beBjorn Bringert            }
102780fe59a7af8b12fbdcd7f6841edaa7f2c2e019dWinson Chung            if (strings != null) {
103780fe59a7af8b12fbdcd7f6841edaa7f2c2e019dWinson Chung                Set<String> newStrings = new HashSet<String>(strings);
1044e871a217b286775dc6c07feb6d9f1d7a7e914beBjorn Bringert                Iterator<String> newStringsIter = newStrings.iterator();
1054e871a217b286775dc6c07feb6d9f1d7a7e914beBjorn Bringert                while (newStringsIter.hasNext()) {
106e0f58d73646871497596fb8f7321d407e7565c28Sunny Goyal                    String encoded = newStringsIter.next();
107e0f58d73646871497596fb8f7321d407e7565c28Sunny Goyal                    PendingInstallShortcutInfo info = decode(encoded, context);
108e0f58d73646871497596fb8f7321d407e7565c28Sunny Goyal                    if (info == null || (packageNames.contains(info.getTargetPackage())
109e0f58d73646871497596fb8f7321d407e7565c28Sunny Goyal                            && user.equals(info.user))) {
110e0f58d73646871497596fb8f7321d407e7565c28Sunny Goyal                        newStringsIter.remove();
111780fe59a7af8b12fbdcd7f6841edaa7f2c2e019dWinson Chung                    }
112780fe59a7af8b12fbdcd7f6841edaa7f2c2e019dWinson Chung                }
113d80439875557e8c94052e5b0f0327b656370b5fdSunny Goyal                sp.edit().putStringSet(APPS_PENDING_INSTALL, newStrings).apply();
114780fe59a7af8b12fbdcd7f6841edaa7f2c2e019dWinson Chung            }
115780fe59a7af8b12fbdcd7f6841edaa7f2c2e019dWinson Chung        }
116780fe59a7af8b12fbdcd7f6841edaa7f2c2e019dWinson Chung    }
117780fe59a7af8b12fbdcd7f6841edaa7f2c2e019dWinson Chung
11848c7a93eb7ef15ef551aee80c179b8e7e0d2399aMichael Jurka    private static ArrayList<PendingInstallShortcutInfo> getAndClearInstallQueue(
119e0f58d73646871497596fb8f7321d407e7565c28Sunny Goyal            SharedPreferences sharedPrefs, Context context) {
12048c7a93eb7ef15ef551aee80c179b8e7e0d2399aMichael Jurka        synchronized(sLock) {
12148c7a93eb7ef15ef551aee80c179b8e7e0d2399aMichael Jurka            Set<String> strings = sharedPrefs.getStringSet(APPS_PENDING_INSTALL, null);
1224e871a217b286775dc6c07feb6d9f1d7a7e914beBjorn Bringert            if (DBG) Log.d(TAG, "Getting and clearing APPS_PENDING_INSTALL: " + strings);
12348c7a93eb7ef15ef551aee80c179b8e7e0d2399aMichael Jurka            if (strings == null) {
12448c7a93eb7ef15ef551aee80c179b8e7e0d2399aMichael Jurka                return new ArrayList<PendingInstallShortcutInfo>();
12548c7a93eb7ef15ef551aee80c179b8e7e0d2399aMichael Jurka            }
12648c7a93eb7ef15ef551aee80c179b8e7e0d2399aMichael Jurka            ArrayList<PendingInstallShortcutInfo> infos =
12748c7a93eb7ef15ef551aee80c179b8e7e0d2399aMichael Jurka                new ArrayList<PendingInstallShortcutInfo>();
128e0f58d73646871497596fb8f7321d407e7565c28Sunny Goyal            for (String encoded : strings) {
129e0f58d73646871497596fb8f7321d407e7565c28Sunny Goyal                PendingInstallShortcutInfo info = decode(encoded, context);
130e0f58d73646871497596fb8f7321d407e7565c28Sunny Goyal                if (info != null) {
13148c7a93eb7ef15ef551aee80c179b8e7e0d2399aMichael Jurka                    infos.add(info);
13248c7a93eb7ef15ef551aee80c179b8e7e0d2399aMichael Jurka                }
13348c7a93eb7ef15ef551aee80c179b8e7e0d2399aMichael Jurka            }
134d80439875557e8c94052e5b0f0327b656370b5fdSunny Goyal            sharedPrefs.edit().putStringSet(APPS_PENDING_INSTALL, new HashSet<String>()).apply();
13548c7a93eb7ef15ef551aee80c179b8e7e0d2399aMichael Jurka            return infos;
13648c7a93eb7ef15ef551aee80c179b8e7e0d2399aMichael Jurka        }
13748c7a93eb7ef15ef551aee80c179b8e7e0d2399aMichael Jurka    }
13848c7a93eb7ef15ef551aee80c179b8e7e0d2399aMichael Jurka
139f561bdf68dd304e1d7c3f7796621a4cc39ca15f2Winson Chung    // Determines whether to defer installing shortcuts immediately until
140f561bdf68dd304e1d7c3f7796621a4cc39ca15f2Winson Chung    // processAllPendingInstalls() is called.
141f561bdf68dd304e1d7c3f7796621a4cc39ca15f2Winson Chung    private static boolean mUseInstallQueue = false;
142f561bdf68dd304e1d7c3f7796621a4cc39ca15f2Winson Chung
14331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    public void onReceive(Context context, Intent data) {
14451ed5b9bc05c6eb37dcb3fe38fa021f1044c0f88Romain Guy        if (!ACTION_INSTALL_SHORTCUT.equals(data.getAction())) {
14551ed5b9bc05c6eb37dcb3fe38fa021f1044c0f88Romain Guy            return;
14651ed5b9bc05c6eb37dcb3fe38fa021f1044c0f88Romain Guy        }
1477606a412c5a7da2d8eff9bd9425c759f7028d888Sunny Goyal        PendingInstallShortcutInfo info = createPendingInfo(context, data);
1487606a412c5a7da2d8eff9bd9425c759f7028d888Sunny Goyal        if (info != null) {
1497606a412c5a7da2d8eff9bd9425c759f7028d888Sunny Goyal            queuePendingShortcutInfo(info, context);
1503290ec4cc220f97460b3b19f28adaf829ea971e1Sunny Goyal        }
1517606a412c5a7da2d8eff9bd9425c759f7028d888Sunny Goyal    }
1524e871a217b286775dc6c07feb6d9f1d7a7e914beBjorn Bringert
1537606a412c5a7da2d8eff9bd9425c759f7028d888Sunny Goyal    /**
1547606a412c5a7da2d8eff9bd9425c759f7028d888Sunny Goyal     * @return true is the extra is either null or is of type {@param type}
1557606a412c5a7da2d8eff9bd9425c759f7028d888Sunny Goyal     */
1567606a412c5a7da2d8eff9bd9425c759f7028d888Sunny Goyal    private static boolean isValidExtraType(Intent intent, String key, Class type) {
1577606a412c5a7da2d8eff9bd9425c759f7028d888Sunny Goyal        Object extra = intent.getParcelableExtra(key);
1587606a412c5a7da2d8eff9bd9425c759f7028d888Sunny Goyal        return extra == null || type.isInstance(extra);
159e0f58d73646871497596fb8f7321d407e7565c28Sunny Goyal    }
160dff0bfeb901e767ca9b57f9b8051c7fd077626e9Nilesh Agrawal
1617606a412c5a7da2d8eff9bd9425c759f7028d888Sunny Goyal    /**
1627606a412c5a7da2d8eff9bd9425c759f7028d888Sunny Goyal     * Verifies the intent and creates a {@link PendingInstallShortcutInfo}
1637606a412c5a7da2d8eff9bd9425c759f7028d888Sunny Goyal     */
1647606a412c5a7da2d8eff9bd9425c759f7028d888Sunny Goyal    private static PendingInstallShortcutInfo createPendingInfo(Context context, Intent data) {
1657606a412c5a7da2d8eff9bd9425c759f7028d888Sunny Goyal        if (!isValidExtraType(data, Intent.EXTRA_SHORTCUT_INTENT, Intent.class) ||
1667606a412c5a7da2d8eff9bd9425c759f7028d888Sunny Goyal                !(isValidExtraType(data, Intent.EXTRA_SHORTCUT_ICON_RESOURCE,
1677606a412c5a7da2d8eff9bd9425c759f7028d888Sunny Goyal                        Intent.ShortcutIconResource.class)) ||
1687606a412c5a7da2d8eff9bd9425c759f7028d888Sunny Goyal                !(isValidExtraType(data, Intent.EXTRA_SHORTCUT_ICON, Bitmap.class))) {
1697606a412c5a7da2d8eff9bd9425c759f7028d888Sunny Goyal
1707606a412c5a7da2d8eff9bd9425c759f7028d888Sunny Goyal            if (DBG) Log.e(TAG, "Invalid install shortcut intent");
1717606a412c5a7da2d8eff9bd9425c759f7028d888Sunny Goyal            return null;
1727606a412c5a7da2d8eff9bd9425c759f7028d888Sunny Goyal        }
1737606a412c5a7da2d8eff9bd9425c759f7028d888Sunny Goyal
1745c97f51fd9443e461a360ff7852aa223c05d667fSunny Goyal        PendingInstallShortcutInfo info = new PendingInstallShortcutInfo(data, context);
1755c97f51fd9443e461a360ff7852aa223c05d667fSunny Goyal        if (info.launchIntent == null || info.label == null) {
1765c97f51fd9443e461a360ff7852aa223c05d667fSunny Goyal            if (DBG) Log.e(TAG, "Invalid install shortcut intent");
1775c97f51fd9443e461a360ff7852aa223c05d667fSunny Goyal            return null;
1785c97f51fd9443e461a360ff7852aa223c05d667fSunny Goyal        }
1797606a412c5a7da2d8eff9bd9425c759f7028d888Sunny Goyal
1807606a412c5a7da2d8eff9bd9425c759f7028d888Sunny Goyal        return convertToLauncherActivityIfPossible(info);
1815c97f51fd9443e461a360ff7852aa223c05d667fSunny Goyal    }
1825c97f51fd9443e461a360ff7852aa223c05d667fSunny Goyal
1837606a412c5a7da2d8eff9bd9425c759f7028d888Sunny Goyal    public static ShortcutInfo fromShortcutIntent(Context context, Intent data) {
1847606a412c5a7da2d8eff9bd9425c759f7028d888Sunny Goyal        PendingInstallShortcutInfo info = createPendingInfo(context, data);
1857606a412c5a7da2d8eff9bd9425c759f7028d888Sunny Goyal        return info == null ? null : info.getShortcutInfo();
186e0f58d73646871497596fb8f7321d407e7565c28Sunny Goyal    }
18748c7a93eb7ef15ef551aee80c179b8e7e0d2399aMichael Jurka
188e0f58d73646871497596fb8f7321d407e7565c28Sunny Goyal    private static void queuePendingShortcutInfo(PendingInstallShortcutInfo info, Context context) {
189de0fb8fbf11caac382589ab464b50d528942273aWinson Chung        // Queue the item up for adding if launcher has not loaded properly yet
190892c74d460ad98c6306420e1127c9aa3e505ba25Winson Chung        LauncherAppState app = LauncherAppState.getInstance();
191e0f58d73646871497596fb8f7321d407e7565c28Sunny Goyal        boolean launcherNotLoaded = app.getModel().getCallback() == null;
192997a92348a6d6e061737399321393449c16cd4d8Winson Chung
193f725824fa2091cab44cf1bcbfe5b5b8d06475560Sunny Goyal        addToInstallQueue(Utilities.getPrefs(context), info);
194997a92348a6d6e061737399321393449c16cd4d8Winson Chung        if (!mUseInstallQueue && !launcherNotLoaded) {
195997a92348a6d6e061737399321393449c16cd4d8Winson Chung            flushInstallQueue(context);
196f561bdf68dd304e1d7c3f7796621a4cc39ca15f2Winson Chung        }
197f561bdf68dd304e1d7c3f7796621a4cc39ca15f2Winson Chung    }
198f561bdf68dd304e1d7c3f7796621a4cc39ca15f2Winson Chung
199f561bdf68dd304e1d7c3f7796621a4cc39ca15f2Winson Chung    static void enableInstallQueue() {
200f561bdf68dd304e1d7c3f7796621a4cc39ca15f2Winson Chung        mUseInstallQueue = true;
201f561bdf68dd304e1d7c3f7796621a4cc39ca15f2Winson Chung    }
202f561bdf68dd304e1d7c3f7796621a4cc39ca15f2Winson Chung    static void disableAndFlushInstallQueue(Context context) {
203f561bdf68dd304e1d7c3f7796621a4cc39ca15f2Winson Chung        mUseInstallQueue = false;
204de0fb8fbf11caac382589ab464b50d528942273aWinson Chung        flushInstallQueue(context);
205de0fb8fbf11caac382589ab464b50d528942273aWinson Chung    }
206de0fb8fbf11caac382589ab464b50d528942273aWinson Chung    static void flushInstallQueue(Context context) {
207f725824fa2091cab44cf1bcbfe5b5b8d06475560Sunny Goyal        SharedPreferences sp = Utilities.getPrefs(context);
208e0f58d73646871497596fb8f7321d407e7565c28Sunny Goyal        ArrayList<PendingInstallShortcutInfo> installQueue = getAndClearInstallQueue(sp, context);
209997a92348a6d6e061737399321393449c16cd4d8Winson Chung        if (!installQueue.isEmpty()) {
210997a92348a6d6e061737399321393449c16cd4d8Winson Chung            Iterator<PendingInstallShortcutInfo> iter = installQueue.iterator();
211997a92348a6d6e061737399321393449c16cd4d8Winson Chung            ArrayList<ItemInfo> addShortcuts = new ArrayList<ItemInfo>();
212997a92348a6d6e061737399321393449c16cd4d8Winson Chung            while (iter.hasNext()) {
213997a92348a6d6e061737399321393449c16cd4d8Winson Chung                final PendingInstallShortcutInfo pendingInfo = iter.next();
214dff0bfeb901e767ca9b57f9b8051c7fd077626e9Nilesh Agrawal
215a28b78e8385f0f590b144038157afc7d34cd48b7Adam Cohen                // If the intent specifies a package, make sure the package exists
216e0f58d73646871497596fb8f7321d407e7565c28Sunny Goyal                String packageName = pendingInfo.getTargetPackage();
217f2048779990bfd3c20b52149f5e8ab208bf2502aSunny Goyal                if (!TextUtils.isEmpty(packageName)) {
218a28b78e8385f0f590b144038157afc7d34cd48b7Adam Cohen                    UserHandleCompat myUserHandle = UserHandleCompat.myUserHandle();
219a28b78e8385f0f590b144038157afc7d34cd48b7Adam Cohen                    if (!LauncherModel.isValidPackage(context, packageName, myUserHandle)) {
220b740f59c7d572d54402e3a74fb2a23c0f1b1af48Sunny Goyal                        if (DBG) Log.d(TAG, "Ignoring shortcut for absent package: "
221b740f59c7d572d54402e3a74fb2a23c0f1b1af48Sunny Goyal                                + pendingInfo.launchIntent);
222a28b78e8385f0f590b144038157afc7d34cd48b7Adam Cohen                        continue;
223a28b78e8385f0f590b144038157afc7d34cd48b7Adam Cohen                    }
224a28b78e8385f0f590b144038157afc7d34cd48b7Adam Cohen                }
225a28b78e8385f0f590b144038157afc7d34cd48b7Adam Cohen
226756adbc3e41ee1edb53c580b8c679f343924fab5Sunny Goyal                // Generate a shortcut info to add into the model
227756adbc3e41ee1edb53c580b8c679f343924fab5Sunny Goyal                addShortcuts.add(pendingInfo.getShortcutInfo());
228f0c6ae0e35d3e020db55b5b826955da66b14b7f6Winson Chung            }
229f0c6ae0e35d3e020db55b5b826955da66b14b7f6Winson Chung
230997a92348a6d6e061737399321393449c16cd4d8Winson Chung            // Add the new apps to the model and bind them
231997a92348a6d6e061737399321393449c16cd4d8Winson Chung            if (!addShortcuts.isEmpty()) {
232997a92348a6d6e061737399321393449c16cd4d8Winson Chung                LauncherAppState app = LauncherAppState.getInstance();
23318bf8e2ffde3444d53aaa9654da02cdedd0b7cd1Sunny Goyal                app.getModel().addAndBindAddedWorkspaceItems(context, addShortcuts);
23431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            }
23531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        }
23631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
23731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
238dff0bfeb901e767ca9b57f9b8051c7fd077626e9Nilesh Agrawal    /**
2392c1afde5cd60eb13f05aeae0c170e697493ef307Winson Chung     * Ensures that we have a valid, non-null name.  If the provided name is null, we will return
2402c1afde5cd60eb13f05aeae0c170e697493ef307Winson Chung     * the application name instead.
2412c1afde5cd60eb13f05aeae0c170e697493ef307Winson Chung     */
242091440a9cb9d4f42406631004aa484cbb79214caAdam Cohen    @Thunk static CharSequence ensureValidName(Context context, Intent intent, CharSequence name) {
2432c1afde5cd60eb13f05aeae0c170e697493ef307Winson Chung        if (name == null) {
2442c1afde5cd60eb13f05aeae0c170e697493ef307Winson Chung            try {
2452c1afde5cd60eb13f05aeae0c170e697493ef307Winson Chung                PackageManager pm = context.getPackageManager();
2462c1afde5cd60eb13f05aeae0c170e697493ef307Winson Chung                ActivityInfo info = pm.getActivityInfo(intent.getComponent(), 0);
24782b016cb56540fe26213e817dd0dd668099c8e20Winson Chung                name = info.loadLabel(pm);
2482c1afde5cd60eb13f05aeae0c170e697493ef307Winson Chung            } catch (PackageManager.NameNotFoundException nnfe) {
2492c1afde5cd60eb13f05aeae0c170e697493ef307Winson Chung                return "";
2502c1afde5cd60eb13f05aeae0c170e697493ef307Winson Chung            }
2512c1afde5cd60eb13f05aeae0c170e697493ef307Winson Chung        }
2522c1afde5cd60eb13f05aeae0c170e697493ef307Winson Chung        return name;
25331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
254e0f58d73646871497596fb8f7321d407e7565c28Sunny Goyal
255e0f58d73646871497596fb8f7321d407e7565c28Sunny Goyal    private static class PendingInstallShortcutInfo {
256e0f58d73646871497596fb8f7321d407e7565c28Sunny Goyal
257e0f58d73646871497596fb8f7321d407e7565c28Sunny Goyal        final LauncherActivityInfoCompat activityInfo;
258e0f58d73646871497596fb8f7321d407e7565c28Sunny Goyal
259e0f58d73646871497596fb8f7321d407e7565c28Sunny Goyal        final Intent data;
260e0f58d73646871497596fb8f7321d407e7565c28Sunny Goyal        final Context mContext;
261e0f58d73646871497596fb8f7321d407e7565c28Sunny Goyal        final Intent launchIntent;
262e0f58d73646871497596fb8f7321d407e7565c28Sunny Goyal        final String label;
263e0f58d73646871497596fb8f7321d407e7565c28Sunny Goyal        final UserHandleCompat user;
264e0f58d73646871497596fb8f7321d407e7565c28Sunny Goyal
265e0f58d73646871497596fb8f7321d407e7565c28Sunny Goyal        /**
266e0f58d73646871497596fb8f7321d407e7565c28Sunny Goyal         * Initializes a PendingInstallShortcutInfo received from a different app.
267e0f58d73646871497596fb8f7321d407e7565c28Sunny Goyal         */
268e0f58d73646871497596fb8f7321d407e7565c28Sunny Goyal        public PendingInstallShortcutInfo(Intent data, Context context) {
269e0f58d73646871497596fb8f7321d407e7565c28Sunny Goyal            this.data = data;
270e0f58d73646871497596fb8f7321d407e7565c28Sunny Goyal            mContext = context;
271e0f58d73646871497596fb8f7321d407e7565c28Sunny Goyal
272e0f58d73646871497596fb8f7321d407e7565c28Sunny Goyal            launchIntent = data.getParcelableExtra(Intent.EXTRA_SHORTCUT_INTENT);
273e0f58d73646871497596fb8f7321d407e7565c28Sunny Goyal            label = data.getStringExtra(Intent.EXTRA_SHORTCUT_NAME);
274e0f58d73646871497596fb8f7321d407e7565c28Sunny Goyal            user = UserHandleCompat.myUserHandle();
275e0f58d73646871497596fb8f7321d407e7565c28Sunny Goyal            activityInfo = null;
276e0f58d73646871497596fb8f7321d407e7565c28Sunny Goyal        }
277e0f58d73646871497596fb8f7321d407e7565c28Sunny Goyal
278e0f58d73646871497596fb8f7321d407e7565c28Sunny Goyal        /**
279e0f58d73646871497596fb8f7321d407e7565c28Sunny Goyal         * Initializes a PendingInstallShortcutInfo to represent a launcher target.
280e0f58d73646871497596fb8f7321d407e7565c28Sunny Goyal         */
281e0f58d73646871497596fb8f7321d407e7565c28Sunny Goyal        public PendingInstallShortcutInfo(LauncherActivityInfoCompat info, Context context) {
282e0f58d73646871497596fb8f7321d407e7565c28Sunny Goyal            this.data = null;
283e0f58d73646871497596fb8f7321d407e7565c28Sunny Goyal            mContext = context;
284e0f58d73646871497596fb8f7321d407e7565c28Sunny Goyal            activityInfo = info;
285e0f58d73646871497596fb8f7321d407e7565c28Sunny Goyal            user = info.getUser();
286e0f58d73646871497596fb8f7321d407e7565c28Sunny Goyal
287e0f58d73646871497596fb8f7321d407e7565c28Sunny Goyal            launchIntent = AppInfo.makeLaunchIntent(context, info, user);
288e0f58d73646871497596fb8f7321d407e7565c28Sunny Goyal            label = info.getLabel().toString();
289e0f58d73646871497596fb8f7321d407e7565c28Sunny Goyal        }
290e0f58d73646871497596fb8f7321d407e7565c28Sunny Goyal
291e0f58d73646871497596fb8f7321d407e7565c28Sunny Goyal        public String encodeToString() {
292e0f58d73646871497596fb8f7321d407e7565c28Sunny Goyal            if (activityInfo != null) {
293e0f58d73646871497596fb8f7321d407e7565c28Sunny Goyal                try {
294e0f58d73646871497596fb8f7321d407e7565c28Sunny Goyal                    // If it a launcher target, we only need component name, and user to
295e0f58d73646871497596fb8f7321d407e7565c28Sunny Goyal                    // recreate this.
296e0f58d73646871497596fb8f7321d407e7565c28Sunny Goyal                    return new JSONStringer()
297e0f58d73646871497596fb8f7321d407e7565c28Sunny Goyal                        .object()
298e0f58d73646871497596fb8f7321d407e7565c28Sunny Goyal                        .key(LAUNCH_INTENT_KEY).value(launchIntent.toUri(0))
299e0f58d73646871497596fb8f7321d407e7565c28Sunny Goyal                        .key(APP_SHORTCUT_TYPE_KEY).value(true)
300e0f58d73646871497596fb8f7321d407e7565c28Sunny Goyal                        .key(USER_HANDLE_KEY).value(UserManagerCompat.getInstance(mContext)
301e0f58d73646871497596fb8f7321d407e7565c28Sunny Goyal                                .getSerialNumberForUser(user))
302e0f58d73646871497596fb8f7321d407e7565c28Sunny Goyal                        .endObject().toString();
303e0f58d73646871497596fb8f7321d407e7565c28Sunny Goyal                } catch (JSONException e) {
304e0f58d73646871497596fb8f7321d407e7565c28Sunny Goyal                    Log.d(TAG, "Exception when adding shortcut: " + e);
305e0f58d73646871497596fb8f7321d407e7565c28Sunny Goyal                    return null;
306e0f58d73646871497596fb8f7321d407e7565c28Sunny Goyal                }
307e0f58d73646871497596fb8f7321d407e7565c28Sunny Goyal            }
308e0f58d73646871497596fb8f7321d407e7565c28Sunny Goyal
309e0f58d73646871497596fb8f7321d407e7565c28Sunny Goyal            if (launchIntent.getAction() == null) {
310e0f58d73646871497596fb8f7321d407e7565c28Sunny Goyal                launchIntent.setAction(Intent.ACTION_VIEW);
311e0f58d73646871497596fb8f7321d407e7565c28Sunny Goyal            } else if (launchIntent.getAction().equals(Intent.ACTION_MAIN) &&
312e0f58d73646871497596fb8f7321d407e7565c28Sunny Goyal                    launchIntent.getCategories() != null &&
313e0f58d73646871497596fb8f7321d407e7565c28Sunny Goyal                    launchIntent.getCategories().contains(Intent.CATEGORY_LAUNCHER)) {
314e0f58d73646871497596fb8f7321d407e7565c28Sunny Goyal                launchIntent.addFlags(
315e0f58d73646871497596fb8f7321d407e7565c28Sunny Goyal                        Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED);
316e0f58d73646871497596fb8f7321d407e7565c28Sunny Goyal            }
317e0f58d73646871497596fb8f7321d407e7565c28Sunny Goyal
318e0f58d73646871497596fb8f7321d407e7565c28Sunny Goyal            // This name is only used for comparisons and notifications, so fall back to activity
319e0f58d73646871497596fb8f7321d407e7565c28Sunny Goyal            // name if not supplied
320e0f58d73646871497596fb8f7321d407e7565c28Sunny Goyal            String name = ensureValidName(mContext, launchIntent, label).toString();
321e0f58d73646871497596fb8f7321d407e7565c28Sunny Goyal            Bitmap icon = data.getParcelableExtra(Intent.EXTRA_SHORTCUT_ICON);
322e0f58d73646871497596fb8f7321d407e7565c28Sunny Goyal            Intent.ShortcutIconResource iconResource =
323e0f58d73646871497596fb8f7321d407e7565c28Sunny Goyal                data.getParcelableExtra(Intent.EXTRA_SHORTCUT_ICON_RESOURCE);
324e0f58d73646871497596fb8f7321d407e7565c28Sunny Goyal
325e0f58d73646871497596fb8f7321d407e7565c28Sunny Goyal            // Only encode the parameters which are supported by the API.
326e0f58d73646871497596fb8f7321d407e7565c28Sunny Goyal            try {
327e0f58d73646871497596fb8f7321d407e7565c28Sunny Goyal                JSONStringer json = new JSONStringer()
328e0f58d73646871497596fb8f7321d407e7565c28Sunny Goyal                    .object()
329e0f58d73646871497596fb8f7321d407e7565c28Sunny Goyal                    .key(LAUNCH_INTENT_KEY).value(launchIntent.toUri(0))
330e0f58d73646871497596fb8f7321d407e7565c28Sunny Goyal                    .key(NAME_KEY).value(name);
331e0f58d73646871497596fb8f7321d407e7565c28Sunny Goyal                if (icon != null) {
3325b0e669169ea2c951bf2f6f71faf793b24db3c23Sunny Goyal                    byte[] iconByteArray = Utilities.flattenBitmap(icon);
333e0f58d73646871497596fb8f7321d407e7565c28Sunny Goyal                    json = json.key(ICON_KEY).value(
334e0f58d73646871497596fb8f7321d407e7565c28Sunny Goyal                            Base64.encodeToString(
335e0f58d73646871497596fb8f7321d407e7565c28Sunny Goyal                                    iconByteArray, 0, iconByteArray.length, Base64.DEFAULT));
336e0f58d73646871497596fb8f7321d407e7565c28Sunny Goyal                }
337e0f58d73646871497596fb8f7321d407e7565c28Sunny Goyal                if (iconResource != null) {
338e0f58d73646871497596fb8f7321d407e7565c28Sunny Goyal                    json = json.key(ICON_RESOURCE_NAME_KEY).value(iconResource.resourceName);
339e0f58d73646871497596fb8f7321d407e7565c28Sunny Goyal                    json = json.key(ICON_RESOURCE_PACKAGE_NAME_KEY)
340e0f58d73646871497596fb8f7321d407e7565c28Sunny Goyal                            .value(iconResource.packageName);
341e0f58d73646871497596fb8f7321d407e7565c28Sunny Goyal                }
342e0f58d73646871497596fb8f7321d407e7565c28Sunny Goyal                return json.endObject().toString();
343e0f58d73646871497596fb8f7321d407e7565c28Sunny Goyal            } catch (JSONException e) {
344e0f58d73646871497596fb8f7321d407e7565c28Sunny Goyal                Log.d(TAG, "Exception when adding shortcut: " + e);
345e0f58d73646871497596fb8f7321d407e7565c28Sunny Goyal            }
346e0f58d73646871497596fb8f7321d407e7565c28Sunny Goyal            return null;
347e0f58d73646871497596fb8f7321d407e7565c28Sunny Goyal        }
348e0f58d73646871497596fb8f7321d407e7565c28Sunny Goyal
349e0f58d73646871497596fb8f7321d407e7565c28Sunny Goyal        public ShortcutInfo getShortcutInfo() {
350e0f58d73646871497596fb8f7321d407e7565c28Sunny Goyal            if (activityInfo != null) {
35118bf8e2ffde3444d53aaa9654da02cdedd0b7cd1Sunny Goyal                return ShortcutInfo.fromActivityInfo(activityInfo, mContext);
352e0f58d73646871497596fb8f7321d407e7565c28Sunny Goyal            } else {
353e0f58d73646871497596fb8f7321d407e7565c28Sunny Goyal                return LauncherAppState.getInstance().getModel().infoFromShortcutIntent(mContext, data);
354e0f58d73646871497596fb8f7321d407e7565c28Sunny Goyal            }
355e0f58d73646871497596fb8f7321d407e7565c28Sunny Goyal        }
356e0f58d73646871497596fb8f7321d407e7565c28Sunny Goyal
357e0f58d73646871497596fb8f7321d407e7565c28Sunny Goyal        public String getTargetPackage() {
358e0f58d73646871497596fb8f7321d407e7565c28Sunny Goyal            String packageName = launchIntent.getPackage();
359e0f58d73646871497596fb8f7321d407e7565c28Sunny Goyal            if (packageName == null) {
360e0f58d73646871497596fb8f7321d407e7565c28Sunny Goyal                packageName = launchIntent.getComponent() == null ? null :
361e0f58d73646871497596fb8f7321d407e7565c28Sunny Goyal                    launchIntent.getComponent().getPackageName();
362e0f58d73646871497596fb8f7321d407e7565c28Sunny Goyal            }
363e0f58d73646871497596fb8f7321d407e7565c28Sunny Goyal            return packageName;
364e0f58d73646871497596fb8f7321d407e7565c28Sunny Goyal        }
3650b037789662d1c16627dc5b509d1ac55bc76971bSunny Goyal
366b740f59c7d572d54402e3a74fb2a23c0f1b1af48Sunny Goyal        public boolean isLauncherActivity() {
3670b037789662d1c16627dc5b509d1ac55bc76971bSunny Goyal            return activityInfo != null;
3680b037789662d1c16627dc5b509d1ac55bc76971bSunny Goyal        }
369e0f58d73646871497596fb8f7321d407e7565c28Sunny Goyal    }
370e0f58d73646871497596fb8f7321d407e7565c28Sunny Goyal
371e0f58d73646871497596fb8f7321d407e7565c28Sunny Goyal    private static PendingInstallShortcutInfo decode(String encoded, Context context) {
372e0f58d73646871497596fb8f7321d407e7565c28Sunny Goyal        try {
373e0f58d73646871497596fb8f7321d407e7565c28Sunny Goyal            JSONObject object = (JSONObject) new JSONTokener(encoded).nextValue();
374e0f58d73646871497596fb8f7321d407e7565c28Sunny Goyal            Intent launcherIntent = Intent.parseUri(object.getString(LAUNCH_INTENT_KEY), 0);
375e0f58d73646871497596fb8f7321d407e7565c28Sunny Goyal
376e0f58d73646871497596fb8f7321d407e7565c28Sunny Goyal            if (object.optBoolean(APP_SHORTCUT_TYPE_KEY)) {
377e0f58d73646871497596fb8f7321d407e7565c28Sunny Goyal                // The is an internal launcher target shortcut.
378e0f58d73646871497596fb8f7321d407e7565c28Sunny Goyal                UserHandleCompat user = UserManagerCompat.getInstance(context)
379e0f58d73646871497596fb8f7321d407e7565c28Sunny Goyal                        .getUserForSerialNumber(object.getLong(USER_HANDLE_KEY));
38006910a88445c46fb95c9ad5ff83793e37b6af692Sunny Goyal                if (user == null) {
38106910a88445c46fb95c9ad5ff83793e37b6af692Sunny Goyal                    return null;
38206910a88445c46fb95c9ad5ff83793e37b6af692Sunny Goyal                }
383e0f58d73646871497596fb8f7321d407e7565c28Sunny Goyal
384e0f58d73646871497596fb8f7321d407e7565c28Sunny Goyal                LauncherActivityInfoCompat info = LauncherAppsCompat.getInstance(context)
385e0f58d73646871497596fb8f7321d407e7565c28Sunny Goyal                        .resolveActivity(launcherIntent, user);
386e0f58d73646871497596fb8f7321d407e7565c28Sunny Goyal                return info == null ? null : new PendingInstallShortcutInfo(info, context);
387e0f58d73646871497596fb8f7321d407e7565c28Sunny Goyal            }
388e0f58d73646871497596fb8f7321d407e7565c28Sunny Goyal
389e0f58d73646871497596fb8f7321d407e7565c28Sunny Goyal            Intent data = new Intent();
390e0f58d73646871497596fb8f7321d407e7565c28Sunny Goyal            data.putExtra(Intent.EXTRA_SHORTCUT_INTENT, launcherIntent);
391e0f58d73646871497596fb8f7321d407e7565c28Sunny Goyal            data.putExtra(Intent.EXTRA_SHORTCUT_NAME, object.getString(NAME_KEY));
392e0f58d73646871497596fb8f7321d407e7565c28Sunny Goyal
393e0f58d73646871497596fb8f7321d407e7565c28Sunny Goyal            String iconBase64 = object.optString(ICON_KEY);
394e0f58d73646871497596fb8f7321d407e7565c28Sunny Goyal            String iconResourceName = object.optString(ICON_RESOURCE_NAME_KEY);
395e0f58d73646871497596fb8f7321d407e7565c28Sunny Goyal            String iconResourcePackageName = object.optString(ICON_RESOURCE_PACKAGE_NAME_KEY);
396e0f58d73646871497596fb8f7321d407e7565c28Sunny Goyal            if (iconBase64 != null && !iconBase64.isEmpty()) {
397e0f58d73646871497596fb8f7321d407e7565c28Sunny Goyal                byte[] iconArray = Base64.decode(iconBase64, Base64.DEFAULT);
398e0f58d73646871497596fb8f7321d407e7565c28Sunny Goyal                Bitmap b = BitmapFactory.decodeByteArray(iconArray, 0, iconArray.length);
399e0f58d73646871497596fb8f7321d407e7565c28Sunny Goyal                data.putExtra(Intent.EXTRA_SHORTCUT_ICON, b);
400e0f58d73646871497596fb8f7321d407e7565c28Sunny Goyal            } else if (iconResourceName != null && !iconResourceName.isEmpty()) {
401e0f58d73646871497596fb8f7321d407e7565c28Sunny Goyal                Intent.ShortcutIconResource iconResource =
402e0f58d73646871497596fb8f7321d407e7565c28Sunny Goyal                    new Intent.ShortcutIconResource();
403e0f58d73646871497596fb8f7321d407e7565c28Sunny Goyal                iconResource.resourceName = iconResourceName;
404e0f58d73646871497596fb8f7321d407e7565c28Sunny Goyal                iconResource.packageName = iconResourcePackageName;
405e0f58d73646871497596fb8f7321d407e7565c28Sunny Goyal                data.putExtra(Intent.EXTRA_SHORTCUT_ICON_RESOURCE, iconResource);
406e0f58d73646871497596fb8f7321d407e7565c28Sunny Goyal            }
407e0f58d73646871497596fb8f7321d407e7565c28Sunny Goyal
408e0f58d73646871497596fb8f7321d407e7565c28Sunny Goyal            return new PendingInstallShortcutInfo(data, context);
409b740f59c7d572d54402e3a74fb2a23c0f1b1af48Sunny Goyal        } catch (JSONException | URISyntaxException e) {
410e0f58d73646871497596fb8f7321d407e7565c28Sunny Goyal            Log.d(TAG, "Exception reading shortcut to add: " + e);
411e0f58d73646871497596fb8f7321d407e7565c28Sunny Goyal        }
412e0f58d73646871497596fb8f7321d407e7565c28Sunny Goyal        return null;
413e0f58d73646871497596fb8f7321d407e7565c28Sunny Goyal    }
4140b037789662d1c16627dc5b509d1ac55bc76971bSunny Goyal
4150b037789662d1c16627dc5b509d1ac55bc76971bSunny Goyal    /**
4160b037789662d1c16627dc5b509d1ac55bc76971bSunny Goyal     * Tries to create a new PendingInstallShortcutInfo which represents the same target,
4170b037789662d1c16627dc5b509d1ac55bc76971bSunny Goyal     * but is an app target and not a shortcut.
4180b037789662d1c16627dc5b509d1ac55bc76971bSunny Goyal     * @return the newly created info or the original one.
4190b037789662d1c16627dc5b509d1ac55bc76971bSunny Goyal     */
4200b037789662d1c16627dc5b509d1ac55bc76971bSunny Goyal    private static PendingInstallShortcutInfo convertToLauncherActivityIfPossible(
4210b037789662d1c16627dc5b509d1ac55bc76971bSunny Goyal            PendingInstallShortcutInfo original) {
422b740f59c7d572d54402e3a74fb2a23c0f1b1af48Sunny Goyal        if (original.isLauncherActivity()) {
4230b037789662d1c16627dc5b509d1ac55bc76971bSunny Goyal            // Already an activity target
4240b037789662d1c16627dc5b509d1ac55bc76971bSunny Goyal            return original;
4250b037789662d1c16627dc5b509d1ac55bc76971bSunny Goyal        }
4265c97f51fd9443e461a360ff7852aa223c05d667fSunny Goyal        if (!Utilities.isLauncherAppTarget(original.launchIntent)
4270b037789662d1c16627dc5b509d1ac55bc76971bSunny Goyal                || !original.user.equals(UserHandleCompat.myUserHandle())) {
4280b037789662d1c16627dc5b509d1ac55bc76971bSunny Goyal            // We can only convert shortcuts which point to a main activity in the current user.
4290b037789662d1c16627dc5b509d1ac55bc76971bSunny Goyal            return original;
4300b037789662d1c16627dc5b509d1ac55bc76971bSunny Goyal        }
4310b037789662d1c16627dc5b509d1ac55bc76971bSunny Goyal
4320b037789662d1c16627dc5b509d1ac55bc76971bSunny Goyal        PackageManager pm = original.mContext.getPackageManager();
4330b037789662d1c16627dc5b509d1ac55bc76971bSunny Goyal        ResolveInfo info = pm.resolveActivity(original.launchIntent, 0);
4340b037789662d1c16627dc5b509d1ac55bc76971bSunny Goyal
4350b037789662d1c16627dc5b509d1ac55bc76971bSunny Goyal        if (info == null) {
4360b037789662d1c16627dc5b509d1ac55bc76971bSunny Goyal            return original;
4370b037789662d1c16627dc5b509d1ac55bc76971bSunny Goyal        }
4380b037789662d1c16627dc5b509d1ac55bc76971bSunny Goyal
4390b037789662d1c16627dc5b509d1ac55bc76971bSunny Goyal        // Ignore any conflicts in the label name, as that can change based on locale.
4400b037789662d1c16627dc5b509d1ac55bc76971bSunny Goyal        LauncherActivityInfoCompat launcherInfo = LauncherActivityInfoCompat
4410b037789662d1c16627dc5b509d1ac55bc76971bSunny Goyal                .fromResolveInfo(info, original.mContext);
4420b037789662d1c16627dc5b509d1ac55bc76971bSunny Goyal        return new PendingInstallShortcutInfo(launcherInfo, original.mContext);
4430b037789662d1c16627dc5b509d1ac55bc76971bSunny Goyal    }
44431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project}
445