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.PackageManager; 26 import android.content.pm.PackageParser; 27 import android.content.pm.PackageParser.PackageParserException; 28 import android.content.res.AssetManager; 29 import android.content.res.Resources; 30 import android.graphics.drawable.Drawable; 31 import android.os.UserHandle; 32 import android.util.Log; 33 import android.view.View; 34 import android.widget.ImageView; 35 import android.widget.TextView; 36 37 import java.io.File; 38 39 /** 40 * This is a utility class for defining some utility methods and constants 41 * used in the package installer application. 42 */ 43 public class PackageUtil { 44 private static final String LOG_TAG = PackageUtil.class.getSimpleName(); 45 46 public static final String PREFIX="com.android.packageinstaller."; 47 public static final String INTENT_ATTR_INSTALL_STATUS = PREFIX+"installStatus"; 48 public static final String INTENT_ATTR_APPLICATION_INFO=PREFIX+"applicationInfo"; 49 public static final String INTENT_ATTR_PERMISSIONS_LIST=PREFIX+"PermissionsList"; 50 //intent attribute strings related to uninstall 51 public static final String INTENT_ATTR_PACKAGE_NAME=PREFIX+"PackageName"; 52 53 /** 54 * Utility method to get package information for a given {@link File} 55 */ getPackageInfo(Context context, File sourceFile)56 public static PackageParser.Package getPackageInfo(Context context, File sourceFile) { 57 final PackageParser parser = new PackageParser(); 58 parser.setCallback(new PackageParser.CallbackImpl(context.getPackageManager())); 59 try { 60 return parser.parsePackage(sourceFile, 0); 61 } catch (PackageParserException e) { 62 return null; 63 } 64 } 65 initSnippet(View snippetView, CharSequence label, Drawable icon)66 public static View initSnippet(View snippetView, CharSequence label, Drawable icon) { 67 ((ImageView)snippetView.findViewById(R.id.app_icon)).setImageDrawable(icon); 68 ((TextView)snippetView.findViewById(R.id.app_name)).setText(label); 69 return snippetView; 70 } 71 72 /** 73 * Utility method to display a snippet of an installed application. 74 * The content view should have been set on context before invoking this method. 75 * appSnippet view should include R.id.app_icon and R.id.app_name 76 * defined on it. 77 * 78 * @param pContext context of package that can load the resources 79 * @param componentInfo ComponentInfo object whose resources are to be loaded 80 * @param snippetView the snippet view 81 */ initSnippetForInstalledApp(Context pContext, ApplicationInfo appInfo, View snippetView)82 public static View initSnippetForInstalledApp(Context pContext, 83 ApplicationInfo appInfo, View snippetView) { 84 return initSnippetForInstalledApp(pContext, appInfo, snippetView, null); 85 } 86 87 /** 88 * Utility method to display a snippet of an installed application. 89 * The content view should have been set on context before invoking this method. 90 * appSnippet view should include R.id.app_icon and R.id.app_name 91 * defined on it. 92 * 93 * @param pContext context of package that can load the resources 94 * @param componentInfo ComponentInfo object whose resources are to be loaded 95 * @param snippetView the snippet view 96 * @param UserHandle user that the app si installed for. 97 */ initSnippetForInstalledApp(Context pContext, ApplicationInfo appInfo, View snippetView, UserHandle user)98 public static View initSnippetForInstalledApp(Context pContext, 99 ApplicationInfo appInfo, View snippetView, UserHandle user) { 100 final PackageManager pm = pContext.getPackageManager(); 101 Drawable icon = appInfo.loadIcon(pm); 102 if (user != null) { 103 icon = pContext.getPackageManager().getUserBadgedIcon(icon, user); 104 } 105 return initSnippet( 106 snippetView, 107 appInfo.loadLabel(pm), 108 icon); 109 } 110 111 static public class AppSnippet { 112 @NonNull public CharSequence label; 113 @Nullable public Drawable icon; AppSnippet(@onNull CharSequence label, @Nullable Drawable icon)114 public AppSnippet(@NonNull CharSequence label, @Nullable Drawable icon) { 115 this.label = label; 116 this.icon = icon; 117 } 118 } 119 120 /** 121 * Utility method to load application label 122 * 123 * @param pContext context of package that can load the resources 124 * @param appInfo ApplicationInfo object of package whose resources are to be loaded 125 * @param sourceFile File the package is in 126 */ getAppSnippet( Activity pContext, ApplicationInfo appInfo, File sourceFile)127 public static AppSnippet getAppSnippet( 128 Activity pContext, ApplicationInfo appInfo, File sourceFile) { 129 final String archiveFilePath = sourceFile.getAbsolutePath(); 130 Resources pRes = pContext.getResources(); 131 AssetManager assmgr = new AssetManager(); 132 assmgr.addAssetPath(archiveFilePath); 133 Resources res = new Resources(assmgr, pRes.getDisplayMetrics(), pRes.getConfiguration()); 134 CharSequence label = null; 135 // Try to load the label from the package's resources. If an app has not explicitly 136 // specified any label, just use the package name. 137 if (appInfo.labelRes != 0) { 138 try { 139 label = res.getText(appInfo.labelRes); 140 } catch (Resources.NotFoundException e) { 141 } 142 } 143 if (label == null) { 144 label = (appInfo.nonLocalizedLabel != null) ? 145 appInfo.nonLocalizedLabel : appInfo.packageName; 146 } 147 Drawable icon = null; 148 // Try to load the icon from the package's resources. If an app has not explicitly 149 // specified any resource, just use the default icon for now. 150 try { 151 if (appInfo.icon != 0) { 152 try { 153 icon = res.getDrawable(appInfo.icon); 154 } catch (Resources.NotFoundException e) { 155 } 156 } 157 if (icon == null) { 158 icon = pContext.getPackageManager().getDefaultActivityIcon(); 159 } 160 } catch (OutOfMemoryError e) { 161 Log.i(LOG_TAG, "Could not load app icon", e); 162 } 163 return new PackageUtil.AppSnippet(label, icon); 164 } 165 166 /** 167 * Get the maximum target sdk for a UID. 168 * 169 * @param context The context to use 170 * @param uid The UID requesting the install/uninstall 171 * 172 * @return The maximum target SDK or -1 if the uid does not match any packages. 173 */ getMaxTargetSdkVersionForUid(@onNull Context context, int uid)174 static int getMaxTargetSdkVersionForUid(@NonNull Context context, int uid) { 175 PackageManager pm = context.getPackageManager(); 176 final String[] packages = pm.getPackagesForUid(uid); 177 int targetSdkVersion = -1; 178 if (packages != null) { 179 for (String packageName : packages) { 180 try { 181 ApplicationInfo info = pm.getApplicationInfo(packageName, 0); 182 targetSdkVersion = Math.max(targetSdkVersion, info.targetSdkVersion); 183 } catch (PackageManager.NameNotFoundException e) { 184 // Ignore and try the next package 185 } 186 } 187 } 188 return targetSdkVersion; 189 } 190 } 191