1 /* 2 * Copyright (C) 2017 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.pm; 18 19 import android.annotation.TargetApi; 20 import android.app.Activity; 21 import android.content.ActivityNotFoundException; 22 import android.content.ComponentName; 23 import android.content.Context; 24 import android.content.Intent; 25 import android.content.IntentSender; 26 import android.content.pm.ActivityInfo; 27 import android.content.pm.LauncherActivityInfo; 28 import android.content.pm.LauncherApps; 29 import android.content.pm.PackageManager; 30 import android.graphics.drawable.Drawable; 31 import android.os.Build; 32 import android.os.Process; 33 import android.os.UserHandle; 34 import android.util.Log; 35 import android.widget.Toast; 36 37 import androidx.annotation.Nullable; 38 39 import com.android.launcher3.LauncherSettings; 40 import com.android.launcher3.R; 41 import com.android.launcher3.icons.ComponentWithLabelAndIcon; 42 import com.android.launcher3.icons.IconCache; 43 import com.android.launcher3.model.data.WorkspaceItemInfo; 44 import com.android.launcher3.util.PackageUserKey; 45 46 import java.util.ArrayList; 47 import java.util.Collections; 48 import java.util.List; 49 50 /** 51 * Wrapper class for representing a shortcut configure activity. 52 */ 53 public abstract class ShortcutConfigActivityInfo implements ComponentWithLabelAndIcon { 54 55 private static final String TAG = "SCActivityInfo"; 56 57 private final ComponentName mCn; 58 private final UserHandle mUser; 59 ShortcutConfigActivityInfo(ComponentName cn, UserHandle user)60 protected ShortcutConfigActivityInfo(ComponentName cn, UserHandle user) { 61 mCn = cn; 62 mUser = user; 63 } 64 65 @Override getComponent()66 public ComponentName getComponent() { 67 return mCn; 68 } 69 70 @Override getUser()71 public UserHandle getUser() { 72 return mUser; 73 } 74 getItemType()75 public int getItemType() { 76 return LauncherSettings.Favorites.ITEM_TYPE_SHORTCUT; 77 } 78 79 @Override getFullResIcon(IconCache cache)80 public abstract Drawable getFullResIcon(IconCache cache); 81 82 /** 83 * Return a WorkspaceItemInfo, if it can be created directly on drop, without requiring any 84 * {@link #startConfigActivity(Activity, int)}. 85 */ createWorkspaceItemInfo()86 public WorkspaceItemInfo createWorkspaceItemInfo() { 87 return null; 88 } 89 startConfigActivity(Activity activity, int requestCode)90 public boolean startConfigActivity(Activity activity, int requestCode) { 91 Intent intent = new Intent(Intent.ACTION_CREATE_SHORTCUT) 92 .setComponent(getComponent()); 93 try { 94 activity.startActivityForResult(intent, requestCode); 95 return true; 96 } catch (ActivityNotFoundException e) { 97 Toast.makeText(activity, R.string.activity_not_found, Toast.LENGTH_SHORT).show(); 98 } catch (SecurityException e) { 99 Toast.makeText(activity, R.string.activity_not_found, Toast.LENGTH_SHORT).show(); 100 Log.e(TAG, "Launcher does not have the permission to launch " + intent 101 + ". Make sure to create a MAIN intent-filter for the corresponding activity " 102 + "or use the exported attribute for this activity.", e); 103 } 104 return false; 105 } 106 107 /** 108 * Returns true if various properties ({@link #getLabel(PackageManager)}, 109 * {@link #getFullResIcon}) can be safely persisted. 110 */ isPersistable()111 public boolean isPersistable() { 112 return true; 113 } 114 115 static class ShortcutConfigActivityInfoVL extends ShortcutConfigActivityInfo { 116 117 private final ActivityInfo mInfo; 118 ShortcutConfigActivityInfoVL(ActivityInfo info)119 ShortcutConfigActivityInfoVL(ActivityInfo info) { 120 super(new ComponentName(info.packageName, info.name), Process.myUserHandle()); 121 mInfo = info; 122 } 123 124 @Override getLabel(PackageManager pm)125 public CharSequence getLabel(PackageManager pm) { 126 return mInfo.loadLabel(pm); 127 } 128 129 @Override getFullResIcon(IconCache cache)130 public Drawable getFullResIcon(IconCache cache) { 131 return cache.getFullResIcon(mInfo); 132 } 133 } 134 135 @TargetApi(26) 136 public static class ShortcutConfigActivityInfoVO extends ShortcutConfigActivityInfo { 137 138 private final LauncherActivityInfo mInfo; 139 ShortcutConfigActivityInfoVO(LauncherActivityInfo info)140 public ShortcutConfigActivityInfoVO(LauncherActivityInfo info) { 141 super(info.getComponentName(), info.getUser()); 142 mInfo = info; 143 } 144 145 @Override getLabel(PackageManager pm)146 public CharSequence getLabel(PackageManager pm) { 147 return mInfo.getLabel(); 148 } 149 150 @Override getFullResIcon(IconCache cache)151 public Drawable getFullResIcon(IconCache cache) { 152 return cache.getFullResIcon(mInfo); 153 } 154 155 @Override startConfigActivity(Activity activity, int requestCode)156 public boolean startConfigActivity(Activity activity, int requestCode) { 157 if (getUser().equals(Process.myUserHandle())) { 158 return super.startConfigActivity(activity, requestCode); 159 } 160 IntentSender is = activity.getSystemService(LauncherApps.class) 161 .getShortcutConfigActivityIntent(mInfo); 162 try { 163 activity.startIntentSenderForResult(is, requestCode, null, 0, 0, 0); 164 return true; 165 } catch (IntentSender.SendIntentException e) { 166 Toast.makeText(activity, R.string.activity_not_found, Toast.LENGTH_SHORT).show(); 167 return false; 168 } 169 } 170 } 171 queryList( Context context, @Nullable PackageUserKey packageUser)172 public static List<ShortcutConfigActivityInfo> queryList( 173 Context context, @Nullable PackageUserKey packageUser) { 174 List<ShortcutConfigActivityInfo> result = new ArrayList<>(); 175 UserHandle myUser = Process.myUserHandle(); 176 177 final List<UserHandle> users; 178 final String packageName; 179 if (packageUser == null) { 180 users = UserCache.INSTANCE.get(context).getUserProfiles(); 181 packageName = null; 182 } else { 183 users = Collections.singletonList(packageUser.mUser); 184 packageName = packageUser.mPackageName; 185 } 186 LauncherApps launcherApps = context.getSystemService(LauncherApps.class); 187 for (UserHandle user : users) { 188 boolean ignoreTargetSdk = myUser.equals(user); 189 for (LauncherActivityInfo activityInfo : 190 launcherApps.getShortcutConfigActivityList(packageName, user)) { 191 if (ignoreTargetSdk || activityInfo.getApplicationInfo().targetSdkVersion 192 >= Build.VERSION_CODES.O) { 193 result.add(new ShortcutConfigActivityInfoVO(activityInfo)); 194 } 195 } 196 } 197 return result; 198 } 199 } 200