1 /* 2 * Copyright (C) 2023 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 android.content.pm; 18 19 import android.annotation.FlaggedApi; 20 import android.annotation.NonNull; 21 import android.annotation.Nullable; 22 import android.content.ComponentName; 23 import android.graphics.Bitmap; 24 import android.graphics.Canvas; 25 import android.graphics.drawable.BitmapDrawable; 26 import android.graphics.drawable.Drawable; 27 import android.util.Slog; 28 29 import com.android.internal.util.DataClass; 30 31 import java.io.ByteArrayInputStream; 32 import java.io.ByteArrayOutputStream; 33 import java.io.IOException; 34 import java.util.Objects; 35 36 /** 37 * Contains fields required to show archived package in Launcher. 38 * @see ArchivedPackageInfo 39 */ 40 @DataClass(genBuilder = false, genConstructor = false, genSetters = true) 41 @FlaggedApi(Flags.FLAG_ARCHIVING) 42 public final class ArchivedActivityInfo { 43 private static final String TAG = "ArchivedActivityInfo"; 44 /** The label for the activity. */ 45 private @NonNull CharSequence mLabel; 46 /** The component name of this activity. */ 47 private @NonNull ComponentName mComponentName; 48 /** 49 * Icon of the activity in the app's locale. if null then the default icon would be shown in the 50 * launcher. 51 */ 52 private @Nullable Drawable mIcon; 53 /** Monochrome icon, if defined, of the activity. */ 54 private @Nullable Drawable mMonochromeIcon; 55 ArchivedActivityInfo(@onNull CharSequence label, @NonNull ComponentName componentName)56 public ArchivedActivityInfo(@NonNull CharSequence label, @NonNull ComponentName componentName) { 57 Objects.requireNonNull(label); 58 Objects.requireNonNull(componentName); 59 mLabel = label; 60 mComponentName = componentName; 61 } 62 63 /* @hide */ ArchivedActivityInfo(@onNull ArchivedActivityParcel parcel)64 ArchivedActivityInfo(@NonNull ArchivedActivityParcel parcel) { 65 mLabel = parcel.title; 66 mComponentName = parcel.originalComponentName; 67 mIcon = drawableFromCompressedBitmap(parcel.iconBitmap); 68 mMonochromeIcon = drawableFromCompressedBitmap(parcel.monochromeIconBitmap); 69 } 70 71 /* @hide */ getParcel()72 @NonNull ArchivedActivityParcel getParcel() { 73 var parcel = new ArchivedActivityParcel(); 74 parcel.title = mLabel.toString(); 75 parcel.originalComponentName = mComponentName; 76 parcel.iconBitmap = mIcon == null ? null : 77 bytesFromBitmap(drawableToBitmap(mIcon)); 78 parcel.monochromeIconBitmap = mMonochromeIcon == null ? null : 79 bytesFromBitmap(drawableToBitmap(mMonochromeIcon)); 80 return parcel; 81 } 82 83 /** 84 * Convert a generic drawable into a bitmap. 85 * @hide 86 */ drawableToBitmap(Drawable drawable)87 public static Bitmap drawableToBitmap(Drawable drawable) { 88 return drawableToBitmap(drawable, /* iconSize= */ 0); 89 } 90 91 /** 92 * Same as above, but scale the resulting image to fit iconSize. 93 * @hide 94 */ drawableToBitmap(Drawable drawable, int iconSize)95 public static Bitmap drawableToBitmap(Drawable drawable, int iconSize) { 96 Bitmap bitmap; 97 if (drawable instanceof BitmapDrawable) { 98 bitmap = ((BitmapDrawable) drawable).getBitmap(); 99 } else { 100 if (drawable.getIntrinsicWidth() <= 0 || drawable.getIntrinsicHeight() <= 0) { 101 // Needed for drawables that are just a single color. 102 bitmap = Bitmap.createBitmap(1, 1, Bitmap.Config.ARGB_8888); 103 } else { 104 bitmap = 105 Bitmap.createBitmap( 106 drawable.getIntrinsicWidth(), 107 drawable.getIntrinsicHeight(), 108 Bitmap.Config.ARGB_8888); 109 } 110 111 Canvas canvas = new Canvas(bitmap); 112 drawable.setBounds(0, 0, canvas.getWidth(), canvas.getHeight()); 113 drawable.draw(canvas); 114 } 115 if (iconSize <= 0) { 116 return bitmap; 117 } 118 119 if (bitmap.getWidth() < iconSize || bitmap.getHeight() < iconSize 120 || bitmap.getWidth() > iconSize * 2 || bitmap.getHeight() > iconSize * 2) { 121 var scaledBitmap = Bitmap.createScaledBitmap(bitmap, iconSize, iconSize, true); 122 if (scaledBitmap != bitmap) { 123 bitmap.recycle(); 124 } 125 return scaledBitmap; 126 } 127 return bitmap; 128 } 129 130 /** 131 * Compress bitmap to PNG format. 132 * @hide 133 */ bytesFromBitmap(Bitmap bitmap)134 public static byte[] bytesFromBitmap(Bitmap bitmap) { 135 if (bitmap == null) { 136 return null; 137 } 138 139 try (ByteArrayOutputStream baos = new ByteArrayOutputStream( 140 bitmap.getByteCount())) { 141 bitmap.compress(Bitmap.CompressFormat.PNG, 100, baos); 142 return baos.toByteArray(); 143 } catch (IOException e) { 144 Slog.e(TAG, "Failed to compress bitmap", e); 145 return null; 146 } 147 } 148 drawableFromCompressedBitmap(byte[] bytes)149 private static Drawable drawableFromCompressedBitmap(byte[] bytes) { 150 if (bytes == null) { 151 return null; 152 } 153 return new BitmapDrawable(null /*res*/, new ByteArrayInputStream(bytes)); 154 } 155 156 157 158 // Code below generated by codegen v1.0.23. 159 // 160 // DO NOT MODIFY! 161 // CHECKSTYLE:OFF Generated code 162 // 163 // To regenerate run: 164 // $ codegen $ANDROID_BUILD_TOP/frameworks/base/core/java/android/content/pm/ArchivedActivityInfo.java 165 // 166 // To exclude the generated code from IntelliJ auto-formatting enable (one-time): 167 // Settings > Editor > Code Style > Formatter Control 168 //@formatter:off 169 170 171 /** 172 * The label for the activity. 173 */ 174 @DataClass.Generated.Member getLabel()175 public @NonNull CharSequence getLabel() { 176 return mLabel; 177 } 178 179 /** 180 * The component name of this activity. 181 */ 182 @DataClass.Generated.Member getComponentName()183 public @NonNull ComponentName getComponentName() { 184 return mComponentName; 185 } 186 187 /** 188 * Icon of the activity in the app's locale. if null then the default icon would be shown in the 189 * launcher. 190 */ 191 @DataClass.Generated.Member getIcon()192 public @Nullable Drawable getIcon() { 193 return mIcon; 194 } 195 196 /** 197 * Monochrome icon, if defined, of the activity. 198 */ 199 @DataClass.Generated.Member getMonochromeIcon()200 public @Nullable Drawable getMonochromeIcon() { 201 return mMonochromeIcon; 202 } 203 204 /** 205 * The label for the activity. 206 */ 207 @DataClass.Generated.Member setLabel(@onNull CharSequence value)208 public @NonNull ArchivedActivityInfo setLabel(@NonNull CharSequence value) { 209 mLabel = value; 210 com.android.internal.util.AnnotationValidations.validate( 211 NonNull.class, null, mLabel); 212 return this; 213 } 214 215 /** 216 * The component name of this activity. 217 */ 218 @DataClass.Generated.Member setComponentName(@onNull ComponentName value)219 public @NonNull ArchivedActivityInfo setComponentName(@NonNull ComponentName value) { 220 mComponentName = value; 221 com.android.internal.util.AnnotationValidations.validate( 222 NonNull.class, null, mComponentName); 223 return this; 224 } 225 226 /** 227 * Icon of the activity in the app's locale. if null then the default icon would be shown in the 228 * launcher. 229 */ 230 @DataClass.Generated.Member setIcon(@onNull Drawable value)231 public @NonNull ArchivedActivityInfo setIcon(@NonNull Drawable value) { 232 mIcon = value; 233 return this; 234 } 235 236 /** 237 * Monochrome icon, if defined, of the activity. 238 */ 239 @DataClass.Generated.Member setMonochromeIcon(@onNull Drawable value)240 public @NonNull ArchivedActivityInfo setMonochromeIcon(@NonNull Drawable value) { 241 mMonochromeIcon = value; 242 return this; 243 } 244 245 @DataClass.Generated( 246 time = 1708042076897L, 247 codegenVersion = "1.0.23", 248 sourceFile = "frameworks/base/core/java/android/content/pm/ArchivedActivityInfo.java", 249 inputSignatures = "private static final java.lang.String TAG\nprivate @android.annotation.NonNull java.lang.CharSequence mLabel\nprivate @android.annotation.NonNull android.content.ComponentName mComponentName\nprivate @android.annotation.Nullable android.graphics.drawable.Drawable mIcon\nprivate @android.annotation.Nullable android.graphics.drawable.Drawable mMonochromeIcon\n @android.annotation.NonNull android.content.pm.ArchivedActivityParcel getParcel()\npublic static android.graphics.Bitmap drawableToBitmap(android.graphics.drawable.Drawable)\npublic static android.graphics.Bitmap drawableToBitmap(android.graphics.drawable.Drawable,int)\npublic static byte[] bytesFromBitmap(android.graphics.Bitmap)\nprivate static android.graphics.drawable.Drawable drawableFromCompressedBitmap(byte[])\nclass ArchivedActivityInfo extends java.lang.Object implements []\n@com.android.internal.util.DataClass(genBuilder=false, genConstructor=false, genSetters=true)") 250 @Deprecated __metadata()251 private void __metadata() {} 252 253 254 //@formatter:on 255 // End of generated code 256 257 } 258