1 /* 2 * Copyright 2019 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 com.android.server.pm; 18 19 import static android.os.Process.INVALID_UID; 20 21 import android.annotation.Nullable; 22 import android.content.pm.PackageInstaller; 23 24 import com.android.internal.util.Preconditions; 25 26 import java.util.Objects; 27 28 /** 29 * Immutable class holding information about where the request to install or update an app 30 * came from. 31 */ 32 public final class InstallSource { 33 /** 34 * An instance of InstallSource representing an absence of knowledge of the source of 35 * a package. Used in preference to null. 36 */ 37 static final InstallSource EMPTY = new InstallSource(null /* initiatingPackageName */, 38 null /* originatingPackageName */, null /* installerPackageName */, INVALID_UID, 39 null /* updateOwnerPackageName */, null /* installerAttributionTag */, 40 false /* isOrphaned */, false /* isInitiatingPackageUninstalled */, 41 null /* initiatingPackageSignatures */, PackageInstaller.PACKAGE_SOURCE_UNSPECIFIED); 42 43 /** We also memoize this case because it is common - all un-updated system apps. */ 44 private static final InstallSource EMPTY_ORPHANED = new InstallSource( 45 null /* initiatingPackageName */, null /* originatingPackageName */, 46 null /* installerPackageName */, INVALID_UID, null /* updateOwnerPackageName */, 47 null /* installerAttributionTag */, true /* isOrphaned */, 48 false /* isInitiatingPackageUninstalled */, null /* initiatingPackageSignatures */, 49 PackageInstaller.PACKAGE_SOURCE_UNSPECIFIED); 50 51 /** 52 * The package that requested the installation, if known. May not correspond to a currently 53 * installed package if {@link #mIsInitiatingPackageUninstalled} is true. 54 */ 55 @Nullable 56 final String mInitiatingPackageName; 57 58 /** 59 * The signing details of the initiating package, if known. Always null if 60 * {@link #mInitiatingPackageName} is null. 61 */ 62 @Nullable 63 final PackageSignatures mInitiatingPackageSignatures; 64 65 /** 66 * The package on behalf of which the initiating package requested the installation, if any. 67 * For example if a downloaded APK is installed via the Package Installer this could be the 68 * app that performed the download. This value is provided by the initiating package and not 69 * verified by the framework. 70 */ 71 @Nullable 72 final String mOriginatingPackageName; 73 74 /** 75 * Package name of the app that installed this package (the installer of record). Note that 76 * this may be modified. 77 */ 78 @Nullable 79 final String mInstallerPackageName; 80 81 /** 82 * Package name of the app that requested the installer ownership. Note that this may be 83 * modified. 84 */ 85 @Nullable 86 final String mUpdateOwnerPackageName; 87 88 /** 89 * UID of the installer package, corresponding to the {@link #mInstallerPackageName}. 90 */ 91 final int mInstallerPackageUid; 92 93 /** 94 * {@link android.content.Context#getAttributionTag()} of installing context. 95 */ 96 @Nullable 97 final String mInstallerAttributionTag; 98 99 /** Indicates if the package that was the installerPackageName has been uninstalled. */ 100 final boolean mIsOrphaned; 101 102 /** 103 * Indicates if the package in initiatingPackageName has been uninstalled. Always false if 104 * {@link #mInitiatingPackageName} is null. 105 */ 106 final boolean mIsInitiatingPackageUninstalled; 107 108 final int mPackageSource; 109 create(@ullable String initiatingPackageName, @Nullable String originatingPackageName, @Nullable String installerPackageName, int installerPackageUid, @Nullable String updateOwnerPackageName, @Nullable String installerAttributionTag, boolean isOrphaned, boolean isInitiatingPackageUninstalled)110 static InstallSource create(@Nullable String initiatingPackageName, 111 @Nullable String originatingPackageName, @Nullable String installerPackageName, 112 int installerPackageUid, @Nullable String updateOwnerPackageName, 113 @Nullable String installerAttributionTag, boolean isOrphaned, 114 boolean isInitiatingPackageUninstalled) { 115 return create(initiatingPackageName, originatingPackageName, installerPackageName, 116 installerPackageUid, updateOwnerPackageName, installerAttributionTag, 117 PackageInstaller.PACKAGE_SOURCE_UNSPECIFIED, isOrphaned, 118 isInitiatingPackageUninstalled); 119 } 120 create(@ullable String initiatingPackageName, @Nullable String originatingPackageName, @Nullable String installerPackageName, int installerPackageUid, @Nullable String updateOwnerPackageName, @Nullable String installerAttributionTag, int packageSource)121 static InstallSource create(@Nullable String initiatingPackageName, 122 @Nullable String originatingPackageName, @Nullable String installerPackageName, 123 int installerPackageUid, @Nullable String updateOwnerPackageName, 124 @Nullable String installerAttributionTag, int packageSource) { 125 return create(initiatingPackageName, originatingPackageName, installerPackageName, 126 installerPackageUid, updateOwnerPackageName, installerAttributionTag, 127 packageSource, false /* isOrphaned */, false /* isInitiatingPackageUninstalled */); 128 } 129 create(@ullable String initiatingPackageName, @Nullable String originatingPackageName, @Nullable String installerPackageName, int installerPackageUid, @Nullable String updateOwnerPackageName, @Nullable String installerAttributionTag, int packageSource, boolean isOrphaned, boolean isInitiatingPackageUninstalled)130 static InstallSource create(@Nullable String initiatingPackageName, 131 @Nullable String originatingPackageName, @Nullable String installerPackageName, 132 int installerPackageUid, @Nullable String updateOwnerPackageName, 133 @Nullable String installerAttributionTag, int packageSource, boolean isOrphaned, 134 boolean isInitiatingPackageUninstalled) { 135 return createInternal( 136 intern(initiatingPackageName), 137 intern(originatingPackageName), 138 intern(installerPackageName), 139 installerPackageUid, 140 intern(updateOwnerPackageName), 141 installerAttributionTag, 142 packageSource, 143 isOrphaned, isInitiatingPackageUninstalled, 144 null /* initiatingPackageSignatures */); 145 } 146 createInternal(@ullable String initiatingPackageName, @Nullable String originatingPackageName, @Nullable String installerPackageName, int installerPackageUid, @Nullable String updateOwnerPackageName, @Nullable String installerAttributionTag, int packageSource, boolean isOrphaned, boolean isInitiatingPackageUninstalled, @Nullable PackageSignatures initiatingPackageSignatures)147 private static InstallSource createInternal(@Nullable String initiatingPackageName, 148 @Nullable String originatingPackageName, @Nullable String installerPackageName, 149 int installerPackageUid, @Nullable String updateOwnerPackageName, 150 @Nullable String installerAttributionTag, int packageSource, boolean isOrphaned, 151 boolean isInitiatingPackageUninstalled, 152 @Nullable PackageSignatures initiatingPackageSignatures) { 153 if (initiatingPackageName == null && originatingPackageName == null 154 && installerPackageName == null && updateOwnerPackageName == null 155 && initiatingPackageSignatures == null 156 && !isInitiatingPackageUninstalled 157 && packageSource == PackageInstaller.PACKAGE_SOURCE_UNSPECIFIED) { 158 return isOrphaned ? EMPTY_ORPHANED : EMPTY; 159 } 160 return new InstallSource(initiatingPackageName, originatingPackageName, 161 installerPackageName, installerPackageUid, updateOwnerPackageName, 162 installerAttributionTag, isOrphaned, isInitiatingPackageUninstalled, 163 initiatingPackageSignatures, packageSource 164 ); 165 } 166 InstallSource(@ullable String initiatingPackageName, @Nullable String originatingPackageName, @Nullable String installerPackageName, int installerPackageUid, @Nullable String updateOwnerPackageName, @Nullable String installerAttributionTag, boolean isOrphaned, boolean isInitiatingPackageUninstalled, @Nullable PackageSignatures initiatingPackageSignatures, int packageSource)167 private InstallSource(@Nullable String initiatingPackageName, 168 @Nullable String originatingPackageName, @Nullable String installerPackageName, 169 int installerPackageUid, @Nullable String updateOwnerPackageName, 170 @Nullable String installerAttributionTag, boolean isOrphaned, 171 boolean isInitiatingPackageUninstalled, 172 @Nullable PackageSignatures initiatingPackageSignatures, 173 int packageSource) { 174 if (initiatingPackageName == null) { 175 Preconditions.checkArgument(initiatingPackageSignatures == null); 176 Preconditions.checkArgument(!isInitiatingPackageUninstalled); 177 } 178 mInitiatingPackageName = initiatingPackageName; 179 mOriginatingPackageName = originatingPackageName; 180 mInstallerPackageName = installerPackageName; 181 mInstallerPackageUid = installerPackageUid; 182 mUpdateOwnerPackageName = updateOwnerPackageName; 183 mInstallerAttributionTag = installerAttributionTag; 184 mIsOrphaned = isOrphaned; 185 mIsInitiatingPackageUninstalled = isInitiatingPackageUninstalled; 186 mInitiatingPackageSignatures = initiatingPackageSignatures; 187 mPackageSource = packageSource; 188 } 189 190 /** 191 * Return an InstallSource the same as this one except with the specified 192 * {@link #mInstallerPackageName}. 193 */ setInstallerPackage(@ullable String installerPackageName, int installerPackageUid)194 InstallSource setInstallerPackage(@Nullable String installerPackageName, 195 int installerPackageUid) { 196 if (Objects.equals(installerPackageName, mInstallerPackageName)) { 197 return this; 198 } 199 return createInternal(mInitiatingPackageName, mOriginatingPackageName, 200 intern(installerPackageName), installerPackageUid, mUpdateOwnerPackageName, 201 mInstallerAttributionTag, mPackageSource, mIsOrphaned, 202 mIsInitiatingPackageUninstalled, mInitiatingPackageSignatures); 203 } 204 205 /** 206 * Return an InstallSource the same as this one except with the specified 207 * {@link #mUpdateOwnerPackageName}. 208 */ setUpdateOwnerPackageName(@ullable String updateOwnerPackageName)209 InstallSource setUpdateOwnerPackageName(@Nullable String updateOwnerPackageName) { 210 if (Objects.equals(updateOwnerPackageName, mUpdateOwnerPackageName)) { 211 return this; 212 } 213 return createInternal(mInitiatingPackageName, mOriginatingPackageName, 214 mInstallerPackageName, mInstallerPackageUid, intern(updateOwnerPackageName), 215 mInstallerAttributionTag, mPackageSource, mIsOrphaned, 216 mIsInitiatingPackageUninstalled, mInitiatingPackageSignatures); 217 } 218 219 /** 220 * Return an InstallSource the same as this one except with the specified value for 221 * {@link #mIsOrphaned}. 222 */ setIsOrphaned(boolean isOrphaned)223 InstallSource setIsOrphaned(boolean isOrphaned) { 224 if (isOrphaned == mIsOrphaned) { 225 return this; 226 } 227 return createInternal(mInitiatingPackageName, mOriginatingPackageName, 228 mInstallerPackageName, mInstallerPackageUid, mUpdateOwnerPackageName, 229 mInstallerAttributionTag, mPackageSource, isOrphaned, 230 mIsInitiatingPackageUninstalled, mInitiatingPackageSignatures); 231 } 232 233 /** 234 * Return an InstallSource the same as this one except with the specified 235 * {@link #mInitiatingPackageSignatures}. 236 */ setInitiatingPackageSignatures(@ullable PackageSignatures signatures)237 InstallSource setInitiatingPackageSignatures(@Nullable PackageSignatures signatures) { 238 if (signatures == mInitiatingPackageSignatures) { 239 return this; 240 } 241 return createInternal(mInitiatingPackageName, mOriginatingPackageName, 242 mInstallerPackageName, mInstallerPackageUid, mUpdateOwnerPackageName, 243 mInstallerAttributionTag, mPackageSource, mIsOrphaned, 244 mIsInitiatingPackageUninstalled, signatures); 245 } 246 247 /** 248 * Return an InstallSource the same as this one updated to reflect that the specified installer 249 * package name has been uninstalled. 250 */ removeInstallerPackage(@ullable String packageName)251 InstallSource removeInstallerPackage(@Nullable String packageName) { 252 if (packageName == null) { 253 return this; 254 } 255 256 boolean modified = false; 257 boolean isInitiatingPackageUninstalled = mIsInitiatingPackageUninstalled; 258 String originatingPackageName = mOriginatingPackageName; 259 String installerPackageName = mInstallerPackageName; 260 String updateOwnerPackageName = mUpdateOwnerPackageName; 261 int installerPackageUid = mInstallerPackageUid; 262 boolean isOrphaned = mIsOrphaned; 263 264 if (packageName.equals(mInitiatingPackageName)) { 265 if (!isInitiatingPackageUninstalled) { 266 // In this case we deliberately do not clear the package name (and signatures). 267 // We allow an app to retrieve details of its own install initiator even after 268 // it has been uninstalled. 269 isInitiatingPackageUninstalled = true; 270 modified = true; 271 } 272 } 273 if (packageName.equals(originatingPackageName)) { 274 originatingPackageName = null; 275 modified = true; 276 } 277 if (packageName.equals(installerPackageName)) { 278 installerPackageName = null; 279 installerPackageUid = INVALID_UID; 280 isOrphaned = true; 281 modified = true; 282 } 283 if (packageName.equals(updateOwnerPackageName)) { 284 updateOwnerPackageName = null; 285 modified = true; 286 } 287 288 if (!modified) { 289 return this; 290 } 291 292 return createInternal(mInitiatingPackageName, originatingPackageName, installerPackageName, 293 installerPackageUid, updateOwnerPackageName, 294 null /* installerAttributionTag */, mPackageSource, isOrphaned, 295 isInitiatingPackageUninstalled, mInitiatingPackageSignatures); 296 } 297 298 @Nullable intern(@ullable String packageName)299 private static String intern(@Nullable String packageName) { 300 return packageName == null ? null : packageName.intern(); 301 } 302 } 303