1 /* 2 * Copyright (C) 2014 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.launcher3.compat; 18 19 import android.content.ComponentName; 20 import android.content.Context; 21 import android.content.Intent; 22 import android.content.pm.ApplicationInfo; 23 import android.content.pm.LauncherActivityInfo; 24 import android.content.pm.LauncherApps; 25 import android.content.pm.PackageManager; 26 import android.content.pm.ResolveInfo; 27 import android.content.pm.ShortcutInfo; 28 import android.graphics.Rect; 29 import android.os.Bundle; 30 import android.os.Process; 31 import android.os.UserHandle; 32 import android.support.annotation.Nullable; 33 34 import com.android.launcher3.compat.ShortcutConfigActivityInfo.ShortcutConfigActivityInfoVL; 35 import com.android.launcher3.shortcuts.ShortcutInfoCompat; 36 import com.android.launcher3.util.PackageUserKey; 37 38 import java.util.ArrayList; 39 import java.util.HashMap; 40 import java.util.List; 41 import java.util.Map; 42 43 public class LauncherAppsCompatVL extends LauncherAppsCompat { 44 45 protected final LauncherApps mLauncherApps; 46 protected final Context mContext; 47 48 private Map<OnAppsChangedCallbackCompat, WrappedCallback> mCallbacks = new HashMap<>(); 49 LauncherAppsCompatVL(Context context)50 LauncherAppsCompatVL(Context context) { 51 mContext = context; 52 mLauncherApps = (LauncherApps) context.getSystemService(Context.LAUNCHER_APPS_SERVICE); 53 } 54 55 @Override getActivityList(String packageName, UserHandle user)56 public List<LauncherActivityInfo> getActivityList(String packageName, UserHandle user) { 57 return mLauncherApps.getActivityList(packageName, user); 58 } 59 60 @Override resolveActivity(Intent intent, UserHandle user)61 public LauncherActivityInfo resolveActivity(Intent intent, UserHandle user) { 62 return mLauncherApps.resolveActivity(intent, user); 63 } 64 65 @Override startActivityForProfile(ComponentName component, UserHandle user, Rect sourceBounds, Bundle opts)66 public void startActivityForProfile(ComponentName component, UserHandle user, 67 Rect sourceBounds, Bundle opts) { 68 mLauncherApps.startMainActivity(component, user, sourceBounds, opts); 69 } 70 71 @Override getApplicationInfo(String packageName, int flags, UserHandle user)72 public ApplicationInfo getApplicationInfo(String packageName, int flags, UserHandle user) { 73 final boolean isPrimaryUser = Process.myUserHandle().equals(user); 74 if (!isPrimaryUser && (flags == 0)) { 75 // We are looking for an installed app on a secondary profile. Prior to O, the only 76 // entry point for work profiles is through the LauncherActivity. 77 List<LauncherActivityInfo> activityList = 78 mLauncherApps.getActivityList(packageName, user); 79 return activityList.size() > 0 ? activityList.get(0).getApplicationInfo() : null; 80 } 81 try { 82 ApplicationInfo info = 83 mContext.getPackageManager().getApplicationInfo(packageName, flags); 84 // There is no way to check if the app is installed for managed profile. But for 85 // primary profile, we can still have this check. 86 if (isPrimaryUser && ((info.flags & ApplicationInfo.FLAG_INSTALLED) == 0) 87 || !info.enabled) { 88 return null; 89 } 90 return info; 91 } catch (PackageManager.NameNotFoundException e) { 92 // Package not found 93 return null; 94 } 95 } 96 97 @Override showAppDetailsForProfile(ComponentName component, UserHandle user, Rect sourceBounds, Bundle opts)98 public void showAppDetailsForProfile(ComponentName component, UserHandle user, 99 Rect sourceBounds, Bundle opts) { 100 mLauncherApps.startAppDetailsActivity(component, user, sourceBounds, opts); 101 } 102 103 @Override addOnAppsChangedCallback(LauncherAppsCompat.OnAppsChangedCallbackCompat callback)104 public void addOnAppsChangedCallback(LauncherAppsCompat.OnAppsChangedCallbackCompat callback) { 105 WrappedCallback wrappedCallback = new WrappedCallback(callback); 106 synchronized (mCallbacks) { 107 mCallbacks.put(callback, wrappedCallback); 108 } 109 mLauncherApps.registerCallback(wrappedCallback); 110 } 111 112 @Override removeOnAppsChangedCallback(OnAppsChangedCallbackCompat callback)113 public void removeOnAppsChangedCallback(OnAppsChangedCallbackCompat callback) { 114 final WrappedCallback wrappedCallback; 115 synchronized (mCallbacks) { 116 wrappedCallback = mCallbacks.remove(callback); 117 } 118 if (wrappedCallback != null) { 119 mLauncherApps.unregisterCallback(wrappedCallback); 120 } 121 } 122 123 @Override isPackageEnabledForProfile(String packageName, UserHandle user)124 public boolean isPackageEnabledForProfile(String packageName, UserHandle user) { 125 return mLauncherApps.isPackageEnabled(packageName, user); 126 } 127 128 @Override isActivityEnabledForProfile(ComponentName component, UserHandle user)129 public boolean isActivityEnabledForProfile(ComponentName component, UserHandle user) { 130 return mLauncherApps.isActivityEnabled(component, user); 131 } 132 133 private static class WrappedCallback extends LauncherApps.Callback { 134 private LauncherAppsCompat.OnAppsChangedCallbackCompat mCallback; 135 WrappedCallback(LauncherAppsCompat.OnAppsChangedCallbackCompat callback)136 public WrappedCallback(LauncherAppsCompat.OnAppsChangedCallbackCompat callback) { 137 mCallback = callback; 138 } 139 onPackageRemoved(String packageName, UserHandle user)140 public void onPackageRemoved(String packageName, UserHandle user) { 141 mCallback.onPackageRemoved(packageName, user); 142 } 143 onPackageAdded(String packageName, UserHandle user)144 public void onPackageAdded(String packageName, UserHandle user) { 145 mCallback.onPackageAdded(packageName, user); 146 } 147 onPackageChanged(String packageName, UserHandle user)148 public void onPackageChanged(String packageName, UserHandle user) { 149 mCallback.onPackageChanged(packageName, user); 150 } 151 onPackagesAvailable(String[] packageNames, UserHandle user, boolean replacing)152 public void onPackagesAvailable(String[] packageNames, UserHandle user, boolean replacing) { 153 mCallback.onPackagesAvailable(packageNames, user, replacing); 154 } 155 onPackagesUnavailable(String[] packageNames, UserHandle user, boolean replacing)156 public void onPackagesUnavailable(String[] packageNames, UserHandle user, 157 boolean replacing) { 158 mCallback.onPackagesUnavailable(packageNames, user, replacing); 159 } 160 onPackagesSuspended(String[] packageNames, UserHandle user)161 public void onPackagesSuspended(String[] packageNames, UserHandle user) { 162 mCallback.onPackagesSuspended(packageNames, user); 163 } 164 onPackagesUnsuspended(String[] packageNames, UserHandle user)165 public void onPackagesUnsuspended(String[] packageNames, UserHandle user) { 166 mCallback.onPackagesUnsuspended(packageNames, user); 167 } 168 onShortcutsChanged(String packageName, List<ShortcutInfo> shortcuts, UserHandle user)169 public void onShortcutsChanged(String packageName, List<ShortcutInfo> shortcuts, 170 UserHandle user) { 171 List<ShortcutInfoCompat> shortcutInfoCompats = new ArrayList<>(shortcuts.size()); 172 for (ShortcutInfo shortcutInfo : shortcuts) { 173 shortcutInfoCompats.add(new ShortcutInfoCompat(shortcutInfo)); 174 } 175 176 mCallback.onShortcutsChanged(packageName, shortcutInfoCompats, user); 177 } 178 } 179 180 @Override getCustomShortcutActivityList( @ullable PackageUserKey packageUser)181 public List<ShortcutConfigActivityInfo> getCustomShortcutActivityList( 182 @Nullable PackageUserKey packageUser) { 183 List<ShortcutConfigActivityInfo> result = new ArrayList<>(); 184 if (packageUser != null && !packageUser.mUser.equals(Process.myUserHandle())) { 185 return result; 186 } 187 PackageManager pm = mContext.getPackageManager(); 188 for (ResolveInfo info : 189 pm.queryIntentActivities(new Intent(Intent.ACTION_CREATE_SHORTCUT), 0)) { 190 if (packageUser == null || packageUser.mPackageName 191 .equals(info.activityInfo.packageName)) { 192 result.add(new ShortcutConfigActivityInfoVL(info.activityInfo, pm)); 193 } 194 } 195 return result; 196 } 197 } 198 199