LauncherAppsCompatVL.java revision ed13187a745866483139e2878037e1f8427ce567
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.graphics.Rect; 23import android.os.Build; 24import android.os.Bundle; 25import android.os.UserHandle; 26 27import java.lang.reflect.InvocationHandler; 28import java.util.ArrayList; 29import java.util.Collections; 30import java.util.HashMap; 31import java.util.List; 32import java.util.Map; 33 34import java.lang.reflect.Proxy; 35import java.lang.reflect.Method; 36 37public class LauncherAppsCompatVL extends LauncherAppsCompat { 38 39 private Object mLauncherApps; 40 private Class mLauncherAppsClass; 41 private Class mListenerClass; 42 private Method mGetActivityList; 43 private Method mResolveActivity; 44 private Method mStartActivityForProfile; 45 private Method mAddOnAppsChangedListener; 46 private Method mRemoveOnAppsChangedListener; 47 private Method mIsPackageEnabledForProfile; 48 private Method mIsActivityEnabledForProfile; 49 50 private Map<OnAppsChangedListenerCompat, Object> mListeners 51 = new HashMap<OnAppsChangedListenerCompat, Object>(); 52 53 static LauncherAppsCompatVL build(Context context, Object launcherApps) { 54 LauncherAppsCompatVL compat = new LauncherAppsCompatVL(context, launcherApps); 55 56 compat.mListenerClass = ReflectUtils.getClassForName( 57 "android.content.pm.LauncherApps$OnAppsChangedListener"); 58 compat.mLauncherAppsClass = ReflectUtils.getClassForName("android.content.pm.LauncherApps"); 59 60 compat.mGetActivityList = ReflectUtils.getMethod(compat.mLauncherAppsClass, 61 "getActivityList", 62 String.class, UserHandle.class); 63 compat.mResolveActivity = ReflectUtils.getMethod(compat.mLauncherAppsClass, 64 "resolveActivity", 65 Intent.class, UserHandle.class); 66 compat.mStartActivityForProfile = ReflectUtils.getMethod(compat.mLauncherAppsClass, 67 "startActivityForProfile", 68 ComponentName.class, Rect.class, Bundle.class, UserHandle.class); 69 compat.mAddOnAppsChangedListener = ReflectUtils.getMethod(compat.mLauncherAppsClass, 70 "addOnAppsChangedListener", compat.mListenerClass); 71 compat.mRemoveOnAppsChangedListener = ReflectUtils.getMethod(compat.mLauncherAppsClass, 72 "removeOnAppsChangedListener", compat.mListenerClass); 73 compat.mIsPackageEnabledForProfile = ReflectUtils.getMethod(compat.mLauncherAppsClass, 74 "isPackageEnabledForProfile", String.class, UserHandle.class); 75 compat.mIsActivityEnabledForProfile = ReflectUtils.getMethod(compat.mLauncherAppsClass, 76 "isActivityEnabledForProfile", ComponentName.class, UserHandle.class); 77 78 if (compat.mListenerClass != null 79 && compat.mLauncherAppsClass != null 80 && compat.mGetActivityList != null 81 && compat.mResolveActivity != null 82 && compat.mStartActivityForProfile != null 83 && compat.mAddOnAppsChangedListener != null 84 && compat.mRemoveOnAppsChangedListener != null 85 && compat.mIsPackageEnabledForProfile != null 86 && compat.mIsActivityEnabledForProfile != null) { 87 return compat; 88 } 89 return null; 90 } 91 92 private LauncherAppsCompatVL(Context context, Object launcherApps) { 93 super(); 94 mLauncherApps = launcherApps; 95 } 96 97 public List<LauncherActivityInfoCompat> getActivityList(String packageName, 98 UserHandleCompat user) { 99 List<Object> list = (List<Object>) ReflectUtils.invokeMethod(mLauncherApps, 100 mGetActivityList, packageName, user.getUser()); 101 if (list.size() == 0) { 102 return Collections.EMPTY_LIST; 103 } 104 ArrayList<LauncherActivityInfoCompat> compatList = 105 new ArrayList<LauncherActivityInfoCompat>(list.size()); 106 for (Object info : list) { 107 compatList.add(new LauncherActivityInfoCompatVL(info)); 108 } 109 return compatList; 110 } 111 112 public LauncherActivityInfoCompat resolveActivity(Intent intent, UserHandleCompat user) { 113 return new LauncherActivityInfoCompatVL(ReflectUtils.invokeMethod(mLauncherApps, 114 mResolveActivity, intent, user.getUser())); 115 } 116 117 public void startActivityForProfile(ComponentName component, Rect sourceBounds, 118 Bundle opts, UserHandleCompat user) { 119 ReflectUtils.invokeMethod(mLauncherApps, mStartActivityForProfile, 120 component, sourceBounds, opts, user.getUser()); 121 } 122 123 public void addOnAppsChangedListener(LauncherAppsCompat.OnAppsChangedListenerCompat listener) { 124 Object wrappedListener = Proxy.newProxyInstance(mListenerClass.getClassLoader(), 125 new Class[]{mListenerClass}, new WrappedListener(listener)); 126 synchronized (mListeners) { 127 mListeners.put(listener, wrappedListener); 128 } 129 ReflectUtils.invokeMethod(mLauncherApps, mAddOnAppsChangedListener, wrappedListener); 130 } 131 132 public void removeOnAppsChangedListener( 133 LauncherAppsCompat.OnAppsChangedListenerCompat listener) { 134 Object wrappedListener = null; 135 synchronized (mListeners) { 136 wrappedListener = mListeners.remove(listener); 137 } 138 if (wrappedListener != null) { 139 ReflectUtils.invokeMethod(mLauncherApps, mRemoveOnAppsChangedListener, wrappedListener); 140 } 141 } 142 143 public boolean isPackageEnabledForProfile(String packageName, UserHandleCompat user) { 144 return (Boolean) ReflectUtils.invokeMethod(mLauncherApps, mIsPackageEnabledForProfile, 145 packageName, user.getUser()); 146 } 147 148 public boolean isActivityEnabledForProfile(ComponentName component, UserHandleCompat user) { 149 return (Boolean) ReflectUtils.invokeMethod(mLauncherApps, mIsActivityEnabledForProfile, 150 component, user.getUser()); 151 } 152 153 private static class WrappedListener implements InvocationHandler { 154 private LauncherAppsCompat.OnAppsChangedListenerCompat mListener; 155 156 public WrappedListener(LauncherAppsCompat.OnAppsChangedListenerCompat listener) { 157 mListener = listener; 158 } 159 160 public Object invoke(Object proxy, Method m, Object[] args) throws Throwable { 161 try { 162 String methodName = m.getName(); 163 if ("onPackageRemoved".equals(methodName)) { 164 onPackageRemoved((UserHandle) args[0], (String) args[1]); 165 } else if ("onPackageAdded".equals(methodName)) { 166 onPackageAdded((UserHandle) args[0], (String) args[1]); 167 } else if ("onPackageChanged".equals(methodName)) { 168 onPackageChanged((UserHandle) args[0], (String) args[1]); 169 } else if ("onPackagesAvailable".equals(methodName)) { 170 onPackagesAvailable((UserHandle) args[0], (String []) args[1], 171 (Boolean) args[2]); 172 } else if ("onPackagesUnavailable".equals(methodName)) { 173 onPackagesUnavailable((UserHandle) args[0], (String []) args[1], 174 (Boolean) args[2]); 175 } 176 } finally { 177 return null; 178 } 179 } 180 181 public void onPackageRemoved(UserHandle user, String packageName) { 182 mListener.onPackageRemoved(UserHandleCompat.fromUser(user), packageName); 183 } 184 185 public void onPackageAdded(UserHandle user, String packageName) { 186 mListener.onPackageAdded(UserHandleCompat.fromUser(user), packageName); 187 } 188 189 public void onPackageChanged(UserHandle user, String packageName) { 190 mListener.onPackageChanged(UserHandleCompat.fromUser(user), packageName); 191 } 192 193 public void onPackagesAvailable(UserHandle user, String[] packageNames, boolean replacing) { 194 mListener.onPackagesAvailable(UserHandleCompat.fromUser(user), packageNames, replacing); 195 } 196 197 public void onPackagesUnavailable(UserHandle user, String[] packageNames, 198 boolean replacing) { 199 mListener.onPackagesUnavailable(UserHandleCompat.fromUser(user), packageNames, 200 replacing); 201 } 202 } 203} 204 205