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