1 /* 2 * Copyright (C) 2021 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 package com.android.launcher3.model.data; 17 18 import static com.android.launcher3.LauncherSettings.Favorites.EXTENDED_CONTAINERS; 19 20 import android.app.PendingIntent; 21 import android.content.Intent; 22 import android.graphics.drawable.Icon; 23 import android.os.Process; 24 import android.os.UserHandle; 25 26 import androidx.annotation.Nullable; 27 28 import com.android.launcher3.LauncherAppState; 29 import com.android.launcher3.LauncherModel; 30 import com.android.launcher3.LauncherSettings; 31 import com.android.launcher3.icons.LauncherIcons; 32 import com.android.launcher3.logger.LauncherAtom.ItemInfo; 33 import com.android.launcher3.logger.LauncherAtom.SearchActionItem; 34 import com.android.launcher3.model.AllAppsList; 35 import com.android.launcher3.model.BaseModelUpdateTask; 36 import com.android.launcher3.model.BgDataModel; 37 38 /** 39 * Represents a SearchAction with in launcher 40 */ 41 public class SearchActionItemInfo extends ItemInfoWithIcon { 42 43 public static final int FLAG_SHOULD_START = 1 << 1; 44 public static final int FLAG_SHOULD_START_FOR_RESULT = FLAG_SHOULD_START | 1 << 2; 45 public static final int FLAG_BADGE_WITH_PACKAGE = 1 << 3; 46 public static final int FLAG_PRIMARY_ICON_FROM_TITLE = 1 << 4; 47 public static final int FLAG_BADGE_WITH_COMPONENT_NAME = 1 << 5; 48 public static final int FLAG_ALLOW_PINNING = 1 << 6; 49 public static final int FLAG_SEARCH_IN_APP = 1 << 7; 50 51 private String mFallbackPackageName; 52 private int mFlags = 0; 53 private Icon mIcon; 54 55 // If true title does not contain any personal info and eligible for logging. 56 private boolean mIsPersonalTitle; 57 private Intent mIntent; 58 59 private PendingIntent mPendingIntent; 60 SearchActionItemInfo(Icon icon, String packageName, UserHandle user, CharSequence title, boolean isPersonalTitle)61 public SearchActionItemInfo(Icon icon, String packageName, UserHandle user, 62 CharSequence title, boolean isPersonalTitle) { 63 mIsPersonalTitle = isPersonalTitle; 64 this.itemType = LauncherSettings.Favorites.ITEM_TYPE_SEARCH_ACTION; 65 this.user = user == null ? Process.myUserHandle() : user; 66 this.title = title; 67 this.container = EXTENDED_CONTAINERS; 68 mFallbackPackageName = packageName; 69 mIcon = icon; 70 } 71 SearchActionItemInfo(SearchActionItemInfo info)72 private SearchActionItemInfo(SearchActionItemInfo info) { 73 super(info); 74 } 75 76 @Override copyFrom(com.android.launcher3.model.data.ItemInfo info)77 public void copyFrom(com.android.launcher3.model.data.ItemInfo info) { 78 super.copyFrom(info); 79 SearchActionItemInfo itemInfo = (SearchActionItemInfo) info; 80 this.mFallbackPackageName = itemInfo.mFallbackPackageName; 81 this.mIcon = itemInfo.mIcon; 82 this.mFlags = itemInfo.mFlags; 83 this.mIsPersonalTitle = itemInfo.mIsPersonalTitle; 84 } 85 86 /** 87 * Returns if multiple flags are all available. 88 */ hasFlags(int flags)89 public boolean hasFlags(int flags) { 90 return (mFlags & flags) != 0; 91 } 92 setFlags(int flags)93 public void setFlags(int flags) { 94 mFlags |= flags; 95 } 96 97 @Override getIntent()98 public Intent getIntent() { 99 return mIntent; 100 } 101 102 /** 103 * Setter for mIntent with assertion for null value mPendingIntent 104 */ setIntent(Intent intent)105 public void setIntent(Intent intent) { 106 if (mPendingIntent != null && intent != null) { 107 throw new RuntimeException( 108 "SearchActionItemInfo can only have either an Intent or a PendingIntent"); 109 } 110 mIntent = intent; 111 } 112 getPendingIntent()113 public PendingIntent getPendingIntent() { 114 return mPendingIntent; 115 } 116 117 /** 118 * Setter of mPendingIntent with assertion for null value mIntent 119 */ setPendingIntent(PendingIntent pendingIntent)120 public void setPendingIntent(PendingIntent pendingIntent) { 121 if (mIntent != null && pendingIntent != null) { 122 throw new RuntimeException( 123 "SearchActionItemInfo can only have either an Intent or a PendingIntent"); 124 } 125 mPendingIntent = pendingIntent; 126 } 127 128 @Nullable getIcon()129 public Icon getIcon() { 130 return mIcon; 131 } 132 133 @Override clone()134 public ItemInfoWithIcon clone() { 135 return new SearchActionItemInfo(this); 136 } 137 138 @Override buildProto(FolderInfo fInfo)139 public ItemInfo buildProto(FolderInfo fInfo) { 140 SearchActionItem.Builder itemBuilder = SearchActionItem.newBuilder() 141 .setPackageName(mFallbackPackageName); 142 143 if (!mIsPersonalTitle) { 144 itemBuilder.setTitle(title.toString()); 145 } 146 return getDefaultItemInfoBuilder() 147 .setSearchActionItem(itemBuilder) 148 .setContainerInfo(getContainerInfo()) 149 .build(); 150 } 151 152 /** 153 * Returns true if result supports drag/drop to home screen 154 */ supportsPinning()155 public boolean supportsPinning() { 156 return hasFlags(FLAG_ALLOW_PINNING) && getIntentPackageName() != null; 157 } 158 159 /** 160 * Creates a {@link WorkspaceItemInfo} coorsponding to search action to be stored in launcher db 161 */ createWorkspaceItem(LauncherModel model)162 public WorkspaceItemInfo createWorkspaceItem(LauncherModel model) { 163 WorkspaceItemInfo info = new WorkspaceItemInfo(); 164 info.title = title; 165 info.bitmap = bitmap; 166 info.intent = mIntent; 167 168 if (hasFlags(FLAG_SHOULD_START_FOR_RESULT)) { 169 info.options |= WorkspaceItemInfo.FLAG_START_FOR_RESULT; 170 } 171 172 model.enqueueModelUpdateTask(new BaseModelUpdateTask() { 173 @Override 174 public void execute(LauncherAppState app, BgDataModel dataModel, AllAppsList apps) { 175 176 model.updateAndBindWorkspaceItem(() -> { 177 PackageItemInfo pkgInfo = new PackageItemInfo(getIntentPackageName(), user); 178 app.getIconCache().getTitleAndIconForApp(pkgInfo, false); 179 try (LauncherIcons li = LauncherIcons.obtain(app.getContext())) { 180 info.bitmap = li.badgeBitmap(info.bitmap.icon, pkgInfo.bitmap); 181 } 182 return info; 183 }); 184 } 185 }); 186 return info; 187 } 188 189 @Nullable getIntentPackageName()190 private String getIntentPackageName() { 191 if (mIntent != null) { 192 if (mIntent.getPackage() != null) return mIntent.getPackage(); 193 return mFallbackPackageName; 194 } 195 return null; 196 } 197 } 198