1 /* 2 ** 3 ** Copyright 2007, The Android Open Source Project 4 ** 5 ** Licensed under the Apache License, Version 2.0 (the "License"); 6 ** you may not use this file except in compliance with the License. 7 ** You may obtain a copy of the License at 8 ** 9 ** http://www.apache.org/licenses/LICENSE-2.0 10 ** 11 ** Unless required by applicable law or agreed to in writing, software 12 ** distributed under the License is distributed on an "AS IS" BASIS, 13 ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 ** See the License for the specific language governing permissions and 15 ** limitations under the License. 16 */ 17 18 package com.android.packageinstaller; 19 20 import android.annotation.NonNull; 21 import android.annotation.Nullable; 22 import android.app.Activity; 23 import android.content.Context; 24 import android.content.pm.ApplicationInfo; 25 import android.content.pm.PackageInfo; 26 import android.content.pm.PackageManager; 27 import android.content.res.AssetManager; 28 import android.content.res.Resources; 29 import android.graphics.drawable.Drawable; 30 import android.os.UserHandle; 31 import android.util.Log; 32 import android.view.View; 33 import android.widget.ImageView; 34 import android.widget.TextView; 35 36 import java.io.File; 37 38 /** 39 * This is a utility class for defining some utility methods and constants 40 * used in the package installer application. 41 */ 42 public class PackageUtil { 43 private static final String LOG_TAG = PackageUtil.class.getSimpleName(); 44 45 public static final String PREFIX="com.android.packageinstaller."; 46 public static final String INTENT_ATTR_INSTALL_STATUS = PREFIX+"installStatus"; 47 public static final String INTENT_ATTR_APPLICATION_INFO=PREFIX+"applicationInfo"; 48 public static final String INTENT_ATTR_PERMISSIONS_LIST=PREFIX+"PermissionsList"; 49 //intent attribute strings related to uninstall 50 public static final String INTENT_ATTR_PACKAGE_NAME=PREFIX+"PackageName"; 51 52 /** 53 * Utility method to get package information for a given {@link File} 54 */ 55 @Nullable getPackageInfo(Context context, File sourceFile, int flags)56 public static PackageInfo getPackageInfo(Context context, File sourceFile, int flags) { 57 try { 58 return context.getPackageManager().getPackageArchiveInfo(sourceFile.getAbsolutePath(), 59 flags); 60 } catch (Exception ignored) { 61 return null; 62 } 63 } 64 initSnippet(View snippetView, CharSequence label, Drawable icon)65 public static View initSnippet(View snippetView, CharSequence label, Drawable icon) { 66 ((ImageView)snippetView.findViewById(R.id.app_icon)).setImageDrawable(icon); 67 ((TextView)snippetView.findViewById(R.id.app_name)).setText(label); 68 return snippetView; 69 } 70 71 /** 72 * Utility method to display a snippet of an installed application. 73 * The content view should have been set on context before invoking this method. 74 * appSnippet view should include R.id.app_icon and R.id.app_name 75 * defined on it. 76 * 77 * @param pContext context of package that can load the resources 78 * @param componentInfo ComponentInfo object whose resources are to be loaded 79 * @param snippetView the snippet view 80 */ initSnippetForInstalledApp(Context pContext, ApplicationInfo appInfo, View snippetView)81 public static View initSnippetForInstalledApp(Context pContext, 82 ApplicationInfo appInfo, View snippetView) { 83 return initSnippetForInstalledApp(pContext, appInfo, snippetView, null); 84 } 85 86 /** 87 * Utility method to display a snippet of an installed application. 88 * The content view should have been set on context before invoking this method. 89 * appSnippet view should include R.id.app_icon and R.id.app_name 90 * defined on it. 91 * 92 * @param pContext context of package that can load the resources 93 * @param componentInfo ComponentInfo object whose resources are to be loaded 94 * @param snippetView the snippet view 95 * @param UserHandle user that the app si installed for. 96 */ initSnippetForInstalledApp(Context pContext, ApplicationInfo appInfo, View snippetView, UserHandle user)97 public static View initSnippetForInstalledApp(Context pContext, 98 ApplicationInfo appInfo, View snippetView, UserHandle user) { 99 final PackageManager pm = pContext.getPackageManager(); 100 Drawable icon = appInfo.loadIcon(pm); 101 if (user != null) { 102 icon = pContext.getPackageManager().getUserBadgedIcon(icon, user); 103 } 104 return initSnippet( 105 snippetView, 106 appInfo.loadLabel(pm), 107 icon); 108 } 109 110 static final class AppSnippet { 111 @NonNull public CharSequence label; 112 @Nullable public Drawable icon; AppSnippet(@onNull CharSequence label, @Nullable Drawable icon)113 public AppSnippet(@NonNull CharSequence label, @Nullable Drawable icon) { 114 this.label = label; 115 this.icon = icon; 116 } 117 118 @Override toString()119 public String toString() { 120 return "AppSnippet[" + label + (icon != null ? "(has" : "(no ") + " icon)]"; 121 } 122 } 123 124 /** 125 * Utility method to load application label 126 * 127 * @param pContext context of package that can load the resources 128 * @param appInfo ApplicationInfo object of package whose resources are to be loaded 129 * @param sourceFile File the package is in 130 */ getAppSnippet( Activity pContext, ApplicationInfo appInfo, File sourceFile)131 public static AppSnippet getAppSnippet( 132 Activity pContext, ApplicationInfo appInfo, File sourceFile) { 133 final String archiveFilePath = sourceFile.getAbsolutePath(); 134 Resources pRes = pContext.getResources(); 135 AssetManager assmgr = new AssetManager(); 136 assmgr.addAssetPath(archiveFilePath); 137 Resources res = new Resources(assmgr, pRes.getDisplayMetrics(), pRes.getConfiguration()); 138 CharSequence label = null; 139 // Try to load the label from the package's resources. If an app has not explicitly 140 // specified any label, just use the package name. 141 if (appInfo.labelRes != 0) { 142 try { 143 label = res.getText(appInfo.labelRes); 144 } catch (Resources.NotFoundException e) { 145 } 146 } 147 if (label == null) { 148 label = (appInfo.nonLocalizedLabel != null) ? 149 appInfo.nonLocalizedLabel : appInfo.packageName; 150 } 151 Drawable icon = null; 152 // Try to load the icon from the package's resources. If an app has not explicitly 153 // specified any resource, just use the default icon for now. 154 try { 155 if (appInfo.icon != 0) { 156 try { 157 icon = res.getDrawable(appInfo.icon); 158 } catch (Resources.NotFoundException e) { 159 } 160 } 161 if (icon == null) { 162 icon = pContext.getPackageManager().getDefaultActivityIcon(); 163 } 164 } catch (OutOfMemoryError e) { 165 Log.i(LOG_TAG, "Could not load app icon", e); 166 } 167 return new PackageUtil.AppSnippet(label, icon); 168 } 169 170 /** 171 * Get the maximum target sdk for a UID. 172 * 173 * @param context The context to use 174 * @param uid The UID requesting the install/uninstall 175 * 176 * @return The maximum target SDK or -1 if the uid does not match any packages. 177 */ getMaxTargetSdkVersionForUid(@onNull Context context, int uid)178 static int getMaxTargetSdkVersionForUid(@NonNull Context context, int uid) { 179 PackageManager pm = context.getPackageManager(); 180 final String[] packages = pm.getPackagesForUid(uid); 181 int targetSdkVersion = -1; 182 if (packages != null) { 183 for (String packageName : packages) { 184 try { 185 ApplicationInfo info = pm.getApplicationInfo(packageName, 0); 186 targetSdkVersion = Math.max(targetSdkVersion, info.targetSdkVersion); 187 } catch (PackageManager.NameNotFoundException e) { 188 // Ignore and try the next package 189 } 190 } 191 } 192 return targetSdkVersion; 193 } 194 } 195