LauncherAppsCompat.java revision e3c59256794448c67e01333a9f5036559b1bd502
1ed13187a745866483139e2878037e1f8427ce567Kenny Guy/* 2ed13187a745866483139e2878037e1f8427ce567Kenny Guy * Copyright (C) 2014 The Android Open Source Project 3ed13187a745866483139e2878037e1f8427ce567Kenny Guy * 4ed13187a745866483139e2878037e1f8427ce567Kenny Guy * Licensed under the Apache License, Version 2.0 (the "License"); 5ed13187a745866483139e2878037e1f8427ce567Kenny Guy * you may not use this file except in compliance with the License. 6ed13187a745866483139e2878037e1f8427ce567Kenny Guy * You may obtain a copy of the License at 7ed13187a745866483139e2878037e1f8427ce567Kenny Guy * 8ed13187a745866483139e2878037e1f8427ce567Kenny Guy * http://www.apache.org/licenses/LICENSE-2.0 9ed13187a745866483139e2878037e1f8427ce567Kenny Guy * 10ed13187a745866483139e2878037e1f8427ce567Kenny Guy * Unless required by applicable law or agreed to in writing, software 11ed13187a745866483139e2878037e1f8427ce567Kenny Guy * distributed under the License is distributed on an "AS IS" BASIS, 12ed13187a745866483139e2878037e1f8427ce567Kenny Guy * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13ed13187a745866483139e2878037e1f8427ce567Kenny Guy * See the License for the specific language governing permissions and 14ed13187a745866483139e2878037e1f8427ce567Kenny Guy * limitations under the License. 15ed13187a745866483139e2878037e1f8427ce567Kenny Guy */ 16ed13187a745866483139e2878037e1f8427ce567Kenny Guy 17ed13187a745866483139e2878037e1f8427ce567Kenny Guypackage com.android.launcher3.compat; 18ed13187a745866483139e2878037e1f8427ce567Kenny Guy 19ed13187a745866483139e2878037e1f8427ce567Kenny Guyimport android.content.ComponentName; 20ed13187a745866483139e2878037e1f8427ce567Kenny Guyimport android.content.Context; 21ed13187a745866483139e2878037e1f8427ce567Kenny Guyimport android.content.Intent; 223ff9047221820a01c6510503466f8c78b43fdc6dCharles Heimport android.content.pm.ApplicationInfo; 233e9be43b6ea75c8b82b57aa58508a0c3e8e1d721Sunny Goyalimport android.content.pm.LauncherActivityInfo; 24ed13187a745866483139e2878037e1f8427ce567Kenny Guyimport android.graphics.Rect; 25ed13187a745866483139e2878037e1f8427ce567Kenny Guyimport android.os.Bundle; 267c74e4ae641e76f73d74348e293c244a157f6585Sunny Goyalimport android.os.UserHandle; 27dec3a908bfa395095e80e4a532cff98612b624deSunny Goyalimport android.support.annotation.Nullable; 28ed13187a745866483139e2878037e1f8427ce567Kenny Guy 29dec3a908bfa395095e80e4a532cff98612b624deSunny Goyalimport com.android.launcher3.LauncherAppState; 308a39b42cc84ee8e1e17861692e0e562c714f3d72Sunny Goyalimport com.android.launcher3.LauncherModel; 31dec3a908bfa395095e80e4a532cff98612b624deSunny Goyalimport com.android.launcher3.ShortcutInfo; 32782f0c9a896db58aeaa60d15f291831b8d7b4c93Sunny Goyalimport com.android.launcher3.Utilities; 33dec3a908bfa395095e80e4a532cff98612b624deSunny Goyalimport com.android.launcher3.graphics.LauncherIcons; 34bfbf7f9f4a0b300613f0ff27a4eb592d88c08325Tony Wickhamimport com.android.launcher3.shortcuts.ShortcutInfoCompat; 358a39b42cc84ee8e1e17861692e0e562c714f3d72Sunny Goyalimport com.android.launcher3.util.LooperExecuter; 3686222d23e28a09a7a26e7a0d4b4830ded2efb384Tony Wickhamimport com.android.launcher3.util.PackageUserKey; 37d794a3f46521b972fa02826d379d1efa112793d2Kenny Guy 38ed13187a745866483139e2878037e1f8427ce567Kenny Guyimport java.util.List; 39ed13187a745866483139e2878037e1f8427ce567Kenny Guy 40ed13187a745866483139e2878037e1f8427ce567Kenny Guypublic abstract class LauncherAppsCompat { 41ed13187a745866483139e2878037e1f8427ce567Kenny Guy 42c2bd8101b8e26b9ebb2c079ae6867229dad3f196Kenny Guy public interface OnAppsChangedCallbackCompat { 437c74e4ae641e76f73d74348e293c244a157f6585Sunny Goyal void onPackageRemoved(String packageName, UserHandle user); 447c74e4ae641e76f73d74348e293c244a157f6585Sunny Goyal void onPackageAdded(String packageName, UserHandle user); 457c74e4ae641e76f73d74348e293c244a157f6585Sunny Goyal void onPackageChanged(String packageName, UserHandle user); 467c74e4ae641e76f73d74348e293c244a157f6585Sunny Goyal void onPackagesAvailable(String[] packageNames, UserHandle user, boolean replacing); 477c74e4ae641e76f73d74348e293c244a157f6585Sunny Goyal void onPackagesUnavailable(String[] packageNames, UserHandle user, boolean replacing); 487c74e4ae641e76f73d74348e293c244a157f6585Sunny Goyal void onPackagesSuspended(String[] packageNames, UserHandle user); 497c74e4ae641e76f73d74348e293c244a157f6585Sunny Goyal void onPackagesUnsuspended(String[] packageNames, UserHandle user); 50bfbf7f9f4a0b300613f0ff27a4eb592d88c08325Tony Wickham void onShortcutsChanged(String packageName, List<ShortcutInfoCompat> shortcuts, 517c74e4ae641e76f73d74348e293c244a157f6585Sunny Goyal UserHandle user); 52ed13187a745866483139e2878037e1f8427ce567Kenny Guy } 53ed13187a745866483139e2878037e1f8427ce567Kenny Guy 54ed13187a745866483139e2878037e1f8427ce567Kenny Guy protected LauncherAppsCompat() { 55ed13187a745866483139e2878037e1f8427ce567Kenny Guy } 56ed13187a745866483139e2878037e1f8427ce567Kenny Guy 57c2bd8101b8e26b9ebb2c079ae6867229dad3f196Kenny Guy private static LauncherAppsCompat sInstance; 58c2bd8101b8e26b9ebb2c079ae6867229dad3f196Kenny Guy private static Object sInstanceLock = new Object(); 59c2bd8101b8e26b9ebb2c079ae6867229dad3f196Kenny Guy 60ed13187a745866483139e2878037e1f8427ce567Kenny Guy public static LauncherAppsCompat getInstance(Context context) { 61c2bd8101b8e26b9ebb2c079ae6867229dad3f196Kenny Guy synchronized (sInstanceLock) { 62c2bd8101b8e26b9ebb2c079ae6867229dad3f196Kenny Guy if (sInstance == null) { 63782f0c9a896db58aeaa60d15f291831b8d7b4c93Sunny Goyal if (Utilities.isAtLeastO()) { 64782f0c9a896db58aeaa60d15f291831b8d7b4c93Sunny Goyal sInstance = new LauncherAppsCompatVO(context.getApplicationContext()); 65782f0c9a896db58aeaa60d15f291831b8d7b4c93Sunny Goyal } else { 66782f0c9a896db58aeaa60d15f291831b8d7b4c93Sunny Goyal sInstance = new LauncherAppsCompatVL(context.getApplicationContext()); 67782f0c9a896db58aeaa60d15f291831b8d7b4c93Sunny Goyal } 68ed13187a745866483139e2878037e1f8427ce567Kenny Guy } 69c2bd8101b8e26b9ebb2c079ae6867229dad3f196Kenny Guy return sInstance; 70ed13187a745866483139e2878037e1f8427ce567Kenny Guy } 71ed13187a745866483139e2878037e1f8427ce567Kenny Guy } 72ed13187a745866483139e2878037e1f8427ce567Kenny Guy 733e9be43b6ea75c8b82b57aa58508a0c3e8e1d721Sunny Goyal public abstract List<LauncherActivityInfo> getActivityList(String packageName, 747c74e4ae641e76f73d74348e293c244a157f6585Sunny Goyal UserHandle user); 753e9be43b6ea75c8b82b57aa58508a0c3e8e1d721Sunny Goyal public abstract LauncherActivityInfo resolveActivity(Intent intent, 767c74e4ae641e76f73d74348e293c244a157f6585Sunny Goyal UserHandle user); 777c74e4ae641e76f73d74348e293c244a157f6585Sunny Goyal public abstract void startActivityForProfile(ComponentName component, UserHandle user, 78c2bd8101b8e26b9ebb2c079ae6867229dad3f196Kenny Guy Rect sourceBounds, Bundle opts); 79ad2e91a216edae0f25bce83a2b058c81953981afSunny Goyal public abstract ApplicationInfo getApplicationInfo( 80ad2e91a216edae0f25bce83a2b058c81953981afSunny Goyal String packageName, int flags, UserHandle user); 81e3c59256794448c67e01333a9f5036559b1bd502Tony public abstract void showAppDetailsForProfile(ComponentName component, UserHandle user, 82e3c59256794448c67e01333a9f5036559b1bd502Tony Rect sourceBounds, Bundle opts); 83c2bd8101b8e26b9ebb2c079ae6867229dad3f196Kenny Guy public abstract void addOnAppsChangedCallback(OnAppsChangedCallbackCompat listener); 84c2bd8101b8e26b9ebb2c079ae6867229dad3f196Kenny Guy public abstract void removeOnAppsChangedCallback(OnAppsChangedCallbackCompat listener); 857c74e4ae641e76f73d74348e293c244a157f6585Sunny Goyal public abstract boolean isPackageEnabledForProfile(String packageName, UserHandle user); 86ed13187a745866483139e2878037e1f8427ce567Kenny Guy public abstract boolean isActivityEnabledForProfile(ComponentName component, 877c74e4ae641e76f73d74348e293c244a157f6585Sunny Goyal UserHandle user); 8886222d23e28a09a7a26e7a0d4b4830ded2efb384Tony Wickham public abstract List<ShortcutConfigActivityInfo> getCustomShortcutActivityList( 8986222d23e28a09a7a26e7a0d4b4830ded2efb384Tony Wickham @Nullable PackageUserKey packageUser); 90dec3a908bfa395095e80e4a532cff98612b624deSunny Goyal 91dec3a908bfa395095e80e4a532cff98612b624deSunny Goyal /** 92dec3a908bfa395095e80e4a532cff98612b624deSunny Goyal * request.accept() will initiate the following flow: 93dec3a908bfa395095e80e4a532cff98612b624deSunny Goyal * -> go-to-system-process for actual processing (a) 94dec3a908bfa395095e80e4a532cff98612b624deSunny Goyal * -> callback-to-launcher on UI thread (b) 95dec3a908bfa395095e80e4a532cff98612b624deSunny Goyal * -> post callback on the worker thread (c) 96dec3a908bfa395095e80e4a532cff98612b624deSunny Goyal * -> Update model and unpin (in system) any shortcut not in out model. (d) 97dec3a908bfa395095e80e4a532cff98612b624deSunny Goyal * 98dec3a908bfa395095e80e4a532cff98612b624deSunny Goyal * Note that (b) will take at-least one frame as it involves posting callback from binder 99dec3a908bfa395095e80e4a532cff98612b624deSunny Goyal * thread to UI thread. 100dec3a908bfa395095e80e4a532cff98612b624deSunny Goyal * If (d) happens before we add this shortcut to our model, we will end up unpinning 101dec3a908bfa395095e80e4a532cff98612b624deSunny Goyal * the shortcut in the system. 102dec3a908bfa395095e80e4a532cff98612b624deSunny Goyal * Here its the caller's responsibility to add the newly created ShortcutInfo immediately 103dec3a908bfa395095e80e4a532cff98612b624deSunny Goyal * to the model (which may involves a single post-to-worker-thread). That will guarantee 104dec3a908bfa395095e80e4a532cff98612b624deSunny Goyal * that (d) happens after model is updated. 105dec3a908bfa395095e80e4a532cff98612b624deSunny Goyal */ 106dec3a908bfa395095e80e4a532cff98612b624deSunny Goyal @Nullable 107dec3a908bfa395095e80e4a532cff98612b624deSunny Goyal public static ShortcutInfo createShortcutInfoFromPinItemRequest( 1088a39b42cc84ee8e1e17861692e0e562c714f3d72Sunny Goyal Context context, final PinItemRequestCompat request, final long acceptDelay) { 109dec3a908bfa395095e80e4a532cff98612b624deSunny Goyal if (request != null && 110dec3a908bfa395095e80e4a532cff98612b624deSunny Goyal request.getRequestType() == PinItemRequestCompat.REQUEST_TYPE_SHORTCUT && 1118a39b42cc84ee8e1e17861692e0e562c714f3d72Sunny Goyal request.isValid()) { 1128a39b42cc84ee8e1e17861692e0e562c714f3d72Sunny Goyal 1138a39b42cc84ee8e1e17861692e0e562c714f3d72Sunny Goyal if (acceptDelay <= 0) { 1148a39b42cc84ee8e1e17861692e0e562c714f3d72Sunny Goyal if (!request.accept()) { 1158a39b42cc84ee8e1e17861692e0e562c714f3d72Sunny Goyal return null; 1168a39b42cc84ee8e1e17861692e0e562c714f3d72Sunny Goyal } 1178a39b42cc84ee8e1e17861692e0e562c714f3d72Sunny Goyal } else { 1188a39b42cc84ee8e1e17861692e0e562c714f3d72Sunny Goyal // Block the worker thread until the accept() is called. 1198a39b42cc84ee8e1e17861692e0e562c714f3d72Sunny Goyal new LooperExecuter(LauncherModel.getWorkerLooper()).execute(new Runnable() { 1208a39b42cc84ee8e1e17861692e0e562c714f3d72Sunny Goyal @Override 1218a39b42cc84ee8e1e17861692e0e562c714f3d72Sunny Goyal public void run() { 1228a39b42cc84ee8e1e17861692e0e562c714f3d72Sunny Goyal try { 1238a39b42cc84ee8e1e17861692e0e562c714f3d72Sunny Goyal Thread.sleep(acceptDelay); 1248a39b42cc84ee8e1e17861692e0e562c714f3d72Sunny Goyal } catch (InterruptedException e) { 1258a39b42cc84ee8e1e17861692e0e562c714f3d72Sunny Goyal // Ignore 1268a39b42cc84ee8e1e17861692e0e562c714f3d72Sunny Goyal } 1278a39b42cc84ee8e1e17861692e0e562c714f3d72Sunny Goyal if (request.isValid()) { 1288a39b42cc84ee8e1e17861692e0e562c714f3d72Sunny Goyal request.accept(); 1298a39b42cc84ee8e1e17861692e0e562c714f3d72Sunny Goyal } 1308a39b42cc84ee8e1e17861692e0e562c714f3d72Sunny Goyal } 1318a39b42cc84ee8e1e17861692e0e562c714f3d72Sunny Goyal }); 1328a39b42cc84ee8e1e17861692e0e562c714f3d72Sunny Goyal } 1338a39b42cc84ee8e1e17861692e0e562c714f3d72Sunny Goyal 134dec3a908bfa395095e80e4a532cff98612b624deSunny Goyal ShortcutInfoCompat compat = new ShortcutInfoCompat(request.getShortcutInfo()); 135dec3a908bfa395095e80e4a532cff98612b624deSunny Goyal ShortcutInfo info = new ShortcutInfo(compat, context); 136dec3a908bfa395095e80e4a532cff98612b624deSunny Goyal // Apply the unbadged icon and fetch the actual icon asynchronously. 137dec3a908bfa395095e80e4a532cff98612b624deSunny Goyal info.iconBitmap = LauncherIcons 138dec3a908bfa395095e80e4a532cff98612b624deSunny Goyal .createShortcutIcon(compat, context, false /* badged */); 139dec3a908bfa395095e80e4a532cff98612b624deSunny Goyal LauncherAppState.getInstance(context).getModel() 140dec3a908bfa395095e80e4a532cff98612b624deSunny Goyal .updateAndBindShortcutInfo(info, compat); 141dec3a908bfa395095e80e4a532cff98612b624deSunny Goyal return info; 142dec3a908bfa395095e80e4a532cff98612b624deSunny Goyal } else { 143dec3a908bfa395095e80e4a532cff98612b624deSunny Goyal return null; 144dec3a908bfa395095e80e4a532cff98612b624deSunny Goyal } 145dec3a908bfa395095e80e4a532cff98612b624deSunny Goyal } 146e3c59256794448c67e01333a9f5036559b1bd502Tony 147e3c59256794448c67e01333a9f5036559b1bd502Tony public void showAppDetailsForProfile(ComponentName component, UserHandle user) { 148e3c59256794448c67e01333a9f5036559b1bd502Tony showAppDetailsForProfile(component, user, null, null); 149e3c59256794448c67e01333a9f5036559b1bd502Tony } 15044cba696386b44f9115cad13ec9ecf67a0ac9119Kenny Guy} 151