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.app.Activity; 21 import android.content.Context; 22 import android.content.pm.ApplicationInfo; 23 import android.content.pm.PackageManager; 24 import android.content.pm.PackageParser; 25 import android.content.pm.PackageParser.PackageParserException; 26 import android.content.res.AssetManager; 27 import android.content.res.Resources; 28 import android.graphics.drawable.Drawable; 29 import android.os.UserHandle; 30 import android.support.annotation.NonNull; 31 import android.support.annotation.Nullable; 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 */ 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 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 */ 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 */ 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 /** 112 * Utility method to display application snippet of a new package. 113 * The content view should have been set on context before invoking this method. 114 * appSnippet view should include R.id.app_icon and R.id.app_name 115 * defined on it. 116 * 117 * @param pContext context of package that can load the resources 118 * @param as The resources to be loaded 119 * @param snippetId view id of app snippet view 120 */ 121 @NonNull public static View initSnippetForNewApp(@NonNull Activity pContext, 122 @NonNull AppSnippet as, int snippetId) { 123 View appSnippet = pContext.findViewById(snippetId); 124 if (as.icon != null) { 125 ((ImageView) appSnippet.findViewById(R.id.app_icon)).setImageDrawable(as.icon); 126 } 127 ((TextView)appSnippet.findViewById(R.id.app_name)).setText(as.label); 128 return appSnippet; 129 } 130 131 static public class AppSnippet { 132 @NonNull public CharSequence label; 133 @Nullable public Drawable icon; 134 public AppSnippet(@NonNull CharSequence label, @Nullable Drawable icon) { 135 this.label = label; 136 this.icon = icon; 137 } 138 } 139 140 /** 141 * Utility method to load application label 142 * 143 * @param pContext context of package that can load the resources 144 * @param appInfo ApplicationInfo object of package whose resources are to be loaded 145 * @param sourceFile File the package is in 146 */ 147 public static AppSnippet getAppSnippet( 148 Activity pContext, ApplicationInfo appInfo, File sourceFile) { 149 final String archiveFilePath = sourceFile.getAbsolutePath(); 150 Resources pRes = pContext.getResources(); 151 AssetManager assmgr = new AssetManager(); 152 assmgr.addAssetPath(archiveFilePath); 153 Resources res = new Resources(assmgr, pRes.getDisplayMetrics(), pRes.getConfiguration()); 154 CharSequence label = null; 155 // Try to load the label from the package's resources. If an app has not explicitly 156 // specified any label, just use the package name. 157 if (appInfo.labelRes != 0) { 158 try { 159 label = res.getText(appInfo.labelRes); 160 } catch (Resources.NotFoundException e) { 161 } 162 } 163 if (label == null) { 164 label = (appInfo.nonLocalizedLabel != null) ? 165 appInfo.nonLocalizedLabel : appInfo.packageName; 166 } 167 Drawable icon = null; 168 // Try to load the icon from the package's resources. If an app has not explicitly 169 // specified any resource, just use the default icon for now. 170 try { 171 if (appInfo.icon != 0) { 172 try { 173 icon = res.getDrawable(appInfo.icon); 174 } catch (Resources.NotFoundException e) { 175 } 176 } 177 if (icon == null) { 178 icon = pContext.getPackageManager().getDefaultActivityIcon(); 179 } 180 } catch (OutOfMemoryError e) { 181 Log.i(LOG_TAG, "Could not load app icon", e); 182 } 183 return new PackageUtil.AppSnippet(label, icon); 184 } 185 186 /** 187 * Get the maximum target sdk for a UID. 188 * 189 * @param context The context to use 190 * @param uid The UID requesting the install/uninstall 191 * 192 * @return The maximum target SDK or -1 if the uid does not match any packages. 193 */ 194 static int getMaxTargetSdkVersionForUid(@NonNull Context context, int uid) { 195 PackageManager pm = context.getPackageManager(); 196 final String[] packages = pm.getPackagesForUid(uid); 197 int targetSdkVersion = -1; 198 if (packages != null) { 199 for (String packageName : packages) { 200 try { 201 ApplicationInfo info = pm.getApplicationInfo(packageName, 0); 202 targetSdkVersion = Math.max(targetSdkVersion, info.targetSdkVersion); 203 } catch (PackageManager.NameNotFoundException e) { 204 // Ignore and try the next package 205 } 206 } 207 } 208 return targetSdkVersion; 209 } 210 } 211