diff options
| -rw-r--r-- | api/current.txt | 12 | ||||
| -rw-r--r-- | core/java/android/app/ApplicationPackageManager.java | 18 | ||||
| -rw-r--r-- | core/java/android/content/pm/IPackageManager.aidl | 3 | ||||
| -rw-r--r-- | core/java/android/content/pm/InstallSourceInfo.aidl | 19 | ||||
| -rw-r--r-- | core/java/android/content/pm/InstallSourceInfo.java | 110 | ||||
| -rw-r--r-- | core/java/android/content/pm/PackageManager.java | 19 | ||||
| -rw-r--r-- | services/core/java/com/android/server/pm/PackageManagerService.java | 91 | ||||
| -rw-r--r-- | services/core/java/com/android/server/pm/Settings.java | 8 |
8 files changed, 263 insertions, 17 deletions
diff --git a/api/current.txt b/api/current.txt index 6ad8ddd4097e..84ebfdbfa39b 100644 --- a/api/current.txt +++ b/api/current.txt @@ -11365,6 +11365,15 @@ package android.content.pm { field public int version; } + public final class InstallSourceInfo implements android.os.Parcelable { + method public int describeContents(); + method @Nullable public String getInitiatingPackageName(); + method @Nullable public String getInstallingPackageName(); + method @Nullable public String getOriginatingPackageName(); + method public void writeToParcel(@NonNull android.os.Parcel, int); + field @NonNull public static final android.os.Parcelable.Creator<android.content.pm.InstallSourceInfo> CREATOR; + } + public class InstrumentationInfo extends android.content.pm.PackageItemInfo implements android.os.Parcelable { ctor public InstrumentationInfo(); ctor public InstrumentationInfo(android.content.pm.InstrumentationInfo); @@ -11729,10 +11738,11 @@ package android.content.pm { method public abstract int getComponentEnabledSetting(@NonNull android.content.ComponentName); method @NonNull public abstract android.graphics.drawable.Drawable getDefaultActivityIcon(); method @Nullable public abstract android.graphics.drawable.Drawable getDrawable(@NonNull String, @DrawableRes int, @Nullable android.content.pm.ApplicationInfo); + method @NonNull public android.content.pm.InstallSourceInfo getInstallSourceInfo(@NonNull String) throws android.content.pm.PackageManager.NameNotFoundException; method @NonNull public abstract java.util.List<android.content.pm.ApplicationInfo> getInstalledApplications(int); method @NonNull public java.util.List<android.content.pm.ModuleInfo> getInstalledModules(int); method @NonNull public abstract java.util.List<android.content.pm.PackageInfo> getInstalledPackages(int); - method @Nullable public abstract String getInstallerPackageName(@NonNull String); + method @Deprecated @Nullable public abstract String getInstallerPackageName(@NonNull String); method @NonNull public abstract byte[] getInstantAppCookie(); method public abstract int getInstantAppCookieMaxBytes(); method @NonNull public abstract android.content.pm.InstrumentationInfo getInstrumentationInfo(@NonNull android.content.ComponentName, int) throws android.content.pm.PackageManager.NameNotFoundException; diff --git a/core/java/android/app/ApplicationPackageManager.java b/core/java/android/app/ApplicationPackageManager.java index 0113f6912183..034826a8d5fa 100644 --- a/core/java/android/app/ApplicationPackageManager.java +++ b/core/java/android/app/ApplicationPackageManager.java @@ -39,6 +39,7 @@ import android.content.pm.IPackageDeleteObserver; import android.content.pm.IPackageManager; import android.content.pm.IPackageMoveObserver; import android.content.pm.IPackageStatsObserver; +import android.content.pm.InstallSourceInfo; import android.content.pm.InstantAppInfo; import android.content.pm.InstrumentationInfo; import android.content.pm.IntentFilterVerificationInfo; @@ -2085,6 +2086,21 @@ public class ApplicationPackageManager extends PackageManager { } @Override + @NonNull + public InstallSourceInfo getInstallSourceInfo(String packageName) throws NameNotFoundException { + final InstallSourceInfo installSourceInfo; + try { + installSourceInfo = mPM.getInstallSourceInfo(packageName); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + if (installSourceInfo == null) { + throw new NameNotFoundException(packageName); + } + return installSourceInfo; + } + + @Override public int getMoveStatus(int moveId) { try { return mPM.getMoveStatus(moveId); @@ -2782,7 +2798,7 @@ public class ApplicationPackageManager extends PackageManager { public Drawable loadUnbadgedItemIcon(@NonNull PackageItemInfo itemInfo, @Nullable ApplicationInfo appInfo) { if (itemInfo.showUserIcon != UserHandle.USER_NULL) { - // Indicates itemInfo is for a different user (e.g. a profile's parent), so use a + // Indicates itemInfo is for a different user (e.g. a profile's parent), so use a // generic user icon (users generally lack permission to view each other's actual icons) int targetUserId = itemInfo.showUserIcon; return UserIcons.getDefaultUserIcon( diff --git a/core/java/android/content/pm/IPackageManager.aidl b/core/java/android/content/pm/IPackageManager.aidl index a71367d562f7..b3d8eb51e324 100644 --- a/core/java/android/content/pm/IPackageManager.aidl +++ b/core/java/android/content/pm/IPackageManager.aidl @@ -26,6 +26,7 @@ import android.content.pm.ChangedPackages; import android.content.pm.InstantAppInfo; import android.content.pm.FeatureInfo; import android.content.pm.IDexModuleRegisterCallback; +import android.content.pm.InstallSourceInfo; import android.content.pm.IPackageInstaller; import android.content.pm.IPackageDeleteObserver; import android.content.pm.IPackageDeleteObserver2; @@ -237,6 +238,8 @@ interface IPackageManager { @UnsupportedAppUsage String getInstallerPackageName(in String packageName); + InstallSourceInfo getInstallSourceInfo(in String packageName); + void resetApplicationPreferences(int userId); @UnsupportedAppUsage diff --git a/core/java/android/content/pm/InstallSourceInfo.aidl b/core/java/android/content/pm/InstallSourceInfo.aidl new file mode 100644 index 000000000000..21ee4c35b57c --- /dev/null +++ b/core/java/android/content/pm/InstallSourceInfo.aidl @@ -0,0 +1,19 @@ +/* + * Copyright 2019 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.content.pm; + +parcelable InstallSourceInfo; diff --git a/core/java/android/content/pm/InstallSourceInfo.java b/core/java/android/content/pm/InstallSourceInfo.java new file mode 100644 index 000000000000..4d235f1af2f7 --- /dev/null +++ b/core/java/android/content/pm/InstallSourceInfo.java @@ -0,0 +1,110 @@ +/* + * Copyright 2019 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.content.pm; + +import android.annotation.NonNull; +import android.annotation.Nullable; +import android.os.Parcel; +import android.os.Parcelable; + +/** + * Information about how an app was installed. + * @see PackageManager#getInstallSourceInfo(String) + */ +public final class InstallSourceInfo implements Parcelable { + + @Nullable private final String mInitiatingPackageName; + + @Nullable private final String mOriginatingPackageName; + + @Nullable private final String mInstallingPackageName; + + /** @hide */ + public InstallSourceInfo(@Nullable String initiatingPackageName, + @Nullable String originatingPackageName, @Nullable String installingPackageName) { + this.mInitiatingPackageName = initiatingPackageName; + this.mOriginatingPackageName = originatingPackageName; + this.mInstallingPackageName = installingPackageName; + } + + @Override + public int describeContents() { + return 0; + } + + @Override + public void writeToParcel(@NonNull Parcel dest, int flags) { + dest.writeString(mInitiatingPackageName); + dest.writeString(mOriginatingPackageName); + dest.writeString(mInstallingPackageName); + } + + private InstallSourceInfo(Parcel source) { + mInitiatingPackageName = source.readString(); + mOriginatingPackageName = source.readString(); + mInstallingPackageName = source.readString(); + } + + /** The name of the package that requested the installation, or null if not available. */ + @Nullable + public String getInitiatingPackageName() { + return mInitiatingPackageName; + } + + /** + * The name of the package on behalf of which the initiating package requested the installation, + * or null if not available. + * <p> + * For example if a downloaded APK is installed via the Package Installer this could be the + * app that performed the download. This value is provided by the initiating package and not + * verified by the framework. + * <p> + * Note that the {@code InstallSourceInfo} returned by + * {@link PackageManager#getInstallSourceInfo(String)} will not have this information + * available unless the calling application holds the INSTALL_PACKAGES permission. + */ + @Nullable + public String getOriginatingPackageName() { + return mOriginatingPackageName; + } + + /** + * The name of the package responsible for the installation (the installer of record), or null + * if not available. + * Note that this may differ from the initiating package name and can be modified. + * + * @see PackageManager#setInstallerPackageName(String, String) + */ + @Nullable + public String getInstallingPackageName() { + return mInstallingPackageName; + } + + @NonNull + public static final Parcelable.Creator<InstallSourceInfo> CREATOR = + new Creator<InstallSourceInfo>() { + @Override + public InstallSourceInfo createFromParcel(Parcel source) { + return new InstallSourceInfo(source); + } + + @Override + public InstallSourceInfo[] newArray(int size) { + return new InstallSourceInfo[size]; + } + }; +} diff --git a/core/java/android/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java index bbfdf910a9da..6e890ba0d827 100644 --- a/core/java/android/content/pm/PackageManager.java +++ b/core/java/android/content/pm/PackageManager.java @@ -5989,11 +5989,30 @@ public abstract class PackageManager { * * @param packageName The name of the package to query * @throws IllegalArgumentException if the given package name is not installed + * + * @deprecated use {@link #getInstallSourceInfo(String)} instead */ + @Deprecated @Nullable public abstract String getInstallerPackageName(@NonNull String packageName); /** + * Retrieves information about how a package was installed or updated. + * <p> + * If the calling application does not hold the INSTALL_PACKAGES permission then + * the result will always return {@code null} from + * {@link InstallSourceInfo#getOriginatingPackageName()}. + * + * @param packageName The name of the package to query + * @throws NameNotFoundException if the given package name is not installed + */ + @NonNull + public InstallSourceInfo getInstallSourceInfo(@NonNull String packageName) + throws NameNotFoundException { + throw new UnsupportedOperationException("getInstallSourceInfo not implemented"); + } + + /** * Attempts to clear the user data directory of an application. * Since this may take a little while, the result will * be posted back to the given observer. A deletion will fail if the diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java index 4e0e4ffb3a13..c5e79426a421 100644 --- a/services/core/java/com/android/server/pm/PackageManagerService.java +++ b/services/core/java/com/android/server/pm/PackageManagerService.java @@ -153,6 +153,7 @@ import android.content.pm.IPackageManager; import android.content.pm.IPackageManagerNative; import android.content.pm.IPackageMoveObserver; import android.content.pm.IPackageStatsObserver; +import android.content.pm.InstallSourceInfo; import android.content.pm.InstantAppInfo; import android.content.pm.InstantAppRequest; import android.content.pm.InstrumentationInfo; @@ -20128,17 +20129,93 @@ public class PackageManagerService extends IPackageManager.Stub public String getInstallerPackageName(String packageName) { final int callingUid = Binder.getCallingUid(); synchronized (mLock) { - final PackageSetting ps = mSettings.mPackages.get(packageName); - if (shouldFilterApplicationLocked( - ps, callingUid, UserHandle.getUserId(callingUid))) { - return null; + final InstallSource installSource = getInstallSourceLocked(packageName, callingUid); + if (installSource == null) { + throw new IllegalArgumentException("Unknown package: " + packageName); } - // InstallerPackageName for Apex is not stored in PackageManager - if (ps == null && mApexManager.isApexPackage(packageName)) { + String installerPackageName = installSource.installerPackageName; + if (installerPackageName != null) { + final PackageSetting ps = mSettings.mPackages.get(installerPackageName); + if (ps == null || shouldFilterApplicationLocked(ps, callingUid, + UserHandle.getUserId(callingUid))) { + installerPackageName = null; + } + } + return installerPackageName; + } + } + + @Override + @Nullable + public InstallSourceInfo getInstallSourceInfo(String packageName) { + final int callingUid = Binder.getCallingUid(); + final int userId = UserHandle.getUserId(callingUid); + + String installerPackageName; + String initiatingPackageName; + String originatingPackageName; + + synchronized (mLock) { + final InstallSource installSource = getInstallSourceLocked(packageName, callingUid); + if (installSource == null) { return null; } - return mSettings.getInstallerPackageNameLPr(packageName); + + installerPackageName = installSource.installerPackageName; + if (installerPackageName != null) { + final PackageSetting ps = mSettings.mPackages.get(installerPackageName); + if (ps == null || shouldFilterApplicationLocked(ps, callingUid, userId)) { + installerPackageName = null; + } + } + + // All installSource strings are interned, so == is ok here + if (installSource.initiatingPackageName == installSource.installerPackageName) { + // The installer and initiator will often be the same, and when they are + // we can skip doing the same check again. + initiatingPackageName = installerPackageName; + } else { + initiatingPackageName = installSource.initiatingPackageName; + final PackageSetting ps = mSettings.mPackages.get(initiatingPackageName); + if (ps == null || shouldFilterApplicationLocked(ps, callingUid, userId)) { + initiatingPackageName = null; + } + + } + originatingPackageName = installSource.originatingPackageName; + if (originatingPackageName != null) { + final PackageSetting ps = mSettings.mPackages.get(originatingPackageName); + if (ps == null || shouldFilterApplicationLocked(ps, callingUid, userId)) { + originatingPackageName = null; + } + } + } + + if (originatingPackageName != null && mContext.checkCallingOrSelfPermission( + Manifest.permission.INSTALL_PACKAGES) != PackageManager.PERMISSION_GRANTED) { + originatingPackageName = null; } + + return new InstallSourceInfo(initiatingPackageName, originatingPackageName, + installerPackageName); + } + + @GuardedBy("mLock") + @Nullable + private InstallSource getInstallSourceLocked(String packageName, int callingUid) { + final PackageSetting ps = mSettings.mPackages.get(packageName); + + // Installer info for Apex is not stored in PackageManager + if (ps == null && mApexManager.isApexPackage(packageName)) { + return InstallSource.EMPTY; + } + + if (ps == null || shouldFilterApplicationLocked(ps, callingUid, + UserHandle.getUserId(callingUid))) { + return null; + } + + return ps.installSource; } public boolean isOrphaned(String packageName) { diff --git a/services/core/java/com/android/server/pm/Settings.java b/services/core/java/com/android/server/pm/Settings.java index f67d3c0f7523..6e67687ae6d7 100644 --- a/services/core/java/com/android/server/pm/Settings.java +++ b/services/core/java/com/android/server/pm/Settings.java @@ -4257,14 +4257,6 @@ public final class Settings { return userState.isMatch(componentInfo, flags); } - String getInstallerPackageNameLPr(String packageName) { - final PackageSetting pkg = mPackages.get(packageName); - if (pkg == null) { - throw new IllegalArgumentException("Unknown package: " + packageName); - } - return pkg.installSource.installerPackageName; - } - boolean isOrphaned(String packageName) { final PackageSetting pkg = mPackages.get(packageName); if (pkg == null) { |