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 17package com.android.launcher3.compat; 18 19import android.content.ComponentName; 20import android.content.Context; 21import android.content.Intent; 22import android.content.pm.ApplicationInfo; 23import android.content.pm.LauncherActivityInfo; 24import android.content.pm.LauncherApps; 25import android.content.pm.PackageManager; 26import android.content.pm.ResolveInfo; 27import android.content.pm.ShortcutInfo; 28import android.graphics.Rect; 29import android.os.Bundle; 30import android.os.Process; 31import android.os.UserHandle; 32import android.support.annotation.Nullable; 33 34import com.android.launcher3.compat.ShortcutConfigActivityInfo.ShortcutConfigActivityInfoVL; 35import com.android.launcher3.shortcuts.ShortcutInfoCompat; 36import com.android.launcher3.util.PackageUserKey; 37 38import java.util.ArrayList; 39import java.util.HashMap; 40import java.util.List; 41import java.util.Map; 42 43public 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 50 LauncherAppsCompatVL(Context context) { 51 mContext = context; 52 mLauncherApps = (LauncherApps) context.getSystemService(Context.LAUNCHER_APPS_SERVICE); 53 } 54 55 @Override 56 public List<LauncherActivityInfo> getActivityList(String packageName, UserHandle user) { 57 return mLauncherApps.getActivityList(packageName, user); 58 } 59 60 @Override 61 public LauncherActivityInfo resolveActivity(Intent intent, UserHandle user) { 62 return mLauncherApps.resolveActivity(intent, user); 63 } 64 65 @Override 66 public void startActivityForProfile(ComponentName component, UserHandle user, 67 Rect sourceBounds, Bundle opts) { 68 mLauncherApps.startMainActivity(component, user, sourceBounds, opts); 69 } 70 71 @Override 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 98 public void showAppDetailsForProfile(ComponentName component, UserHandle user, 99 Rect sourceBounds, Bundle opts) { 100 mLauncherApps.startAppDetailsActivity(component, user, sourceBounds, opts); 101 } 102 103 @Override 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 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 124 public boolean isPackageEnabledForProfile(String packageName, UserHandle user) { 125 return mLauncherApps.isPackageEnabled(packageName, user); 126 } 127 128 @Override 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 136 public WrappedCallback(LauncherAppsCompat.OnAppsChangedCallbackCompat callback) { 137 mCallback = callback; 138 } 139 140 public void onPackageRemoved(String packageName, UserHandle user) { 141 mCallback.onPackageRemoved(packageName, user); 142 } 143 144 public void onPackageAdded(String packageName, UserHandle user) { 145 mCallback.onPackageAdded(packageName, user); 146 } 147 148 public void onPackageChanged(String packageName, UserHandle user) { 149 mCallback.onPackageChanged(packageName, user); 150 } 151 152 public void onPackagesAvailable(String[] packageNames, UserHandle user, boolean replacing) { 153 mCallback.onPackagesAvailable(packageNames, user, replacing); 154 } 155 156 public void onPackagesUnavailable(String[] packageNames, UserHandle user, 157 boolean replacing) { 158 mCallback.onPackagesUnavailable(packageNames, user, replacing); 159 } 160 161 public void onPackagesSuspended(String[] packageNames, UserHandle user) { 162 mCallback.onPackagesSuspended(packageNames, user); 163 } 164 165 public void onPackagesUnsuspended(String[] packageNames, UserHandle user) { 166 mCallback.onPackagesUnsuspended(packageNames, user); 167 } 168 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 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