1 /* 2 * Copyright (C) 2022 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.local; 18 19 import android.annotation.CallSuper; 20 import android.annotation.NonNull; 21 import android.annotation.Nullable; 22 import android.annotation.UserIdInt; 23 import android.content.pm.SigningDetails; 24 import android.os.Binder; 25 import android.os.Build; 26 import android.os.UserHandle; 27 import android.util.ArrayMap; 28 import android.util.apk.ApkSignatureVerifier; 29 30 import com.android.server.pm.Computer; 31 import com.android.server.pm.PackageManagerLocal; 32 import com.android.server.pm.PackageManagerService; 33 import com.android.server.pm.pkg.PackageState; 34 import com.android.server.pm.pkg.SharedUserApi; 35 import com.android.server.pm.snapshot.PackageDataSnapshot; 36 37 import java.io.IOException; 38 import java.util.Collections; 39 import java.util.List; 40 import java.util.Map; 41 42 /** @hide */ 43 public class PackageManagerLocalImpl implements PackageManagerLocal { 44 45 private final PackageManagerService mService; 46 PackageManagerLocalImpl(PackageManagerService service)47 public PackageManagerLocalImpl(PackageManagerService service) { 48 mService = service; 49 } 50 51 @Override reconcileSdkData(@ullable String volumeUuid, @NonNull String packageName, @NonNull List<String> subDirNames, int userId, int appId, int previousAppId, @NonNull String seInfo, int flags)52 public void reconcileSdkData(@Nullable String volumeUuid, @NonNull String packageName, 53 @NonNull List<String> subDirNames, int userId, int appId, int previousAppId, 54 @NonNull String seInfo, int flags) throws IOException { 55 mService.reconcileSdkData(volumeUuid, packageName, subDirNames, userId, appId, 56 previousAppId, seInfo, flags); 57 } 58 59 @NonNull 60 @Override withUnfilteredSnapshot()61 public UnfilteredSnapshotImpl withUnfilteredSnapshot() { 62 return new UnfilteredSnapshotImpl(mService.snapshotComputer(false /*allowLiveComputer*/)); 63 } 64 65 @NonNull 66 @Override withFilteredSnapshot()67 public FilteredSnapshotImpl withFilteredSnapshot() { 68 return withFilteredSnapshot(Binder.getCallingUid(), Binder.getCallingUserHandle()); 69 } 70 71 @NonNull 72 @Override withFilteredSnapshot(int callingUid, @NonNull UserHandle user)73 public FilteredSnapshotImpl withFilteredSnapshot(int callingUid, @NonNull UserHandle user) { 74 return new FilteredSnapshotImpl(callingUid, user, 75 mService.snapshotComputer(false /*allowLiveComputer*/), null); 76 } 77 78 @Override addOverrideSigningDetails(@onNull SigningDetails oldSigningDetails, @NonNull SigningDetails newSigningDetails)79 public void addOverrideSigningDetails(@NonNull SigningDetails oldSigningDetails, 80 @NonNull SigningDetails newSigningDetails) { 81 if (!Build.isDebuggable()) { 82 throw new SecurityException("This test API is only available on debuggable builds"); 83 } 84 ApkSignatureVerifier.addOverrideSigningDetails(oldSigningDetails, newSigningDetails); 85 } 86 87 @Override removeOverrideSigningDetails(@onNull SigningDetails oldSigningDetails)88 public void removeOverrideSigningDetails(@NonNull SigningDetails oldSigningDetails) { 89 if (!Build.isDebuggable()) { 90 throw new SecurityException("This test API is only available on debuggable builds"); 91 } 92 ApkSignatureVerifier.removeOverrideSigningDetails(oldSigningDetails); 93 } 94 95 @Override clearOverrideSigningDetails()96 public void clearOverrideSigningDetails() { 97 if (!Build.isDebuggable()) { 98 throw new SecurityException("This test API is only available on debuggable builds"); 99 } 100 ApkSignatureVerifier.clearOverrideSigningDetails(); 101 } 102 103 private abstract static class BaseSnapshotImpl implements AutoCloseable { 104 105 private boolean mClosed; 106 107 @NonNull 108 protected Computer mSnapshot; 109 BaseSnapshotImpl(@onNull PackageDataSnapshot snapshot)110 private BaseSnapshotImpl(@NonNull PackageDataSnapshot snapshot) { 111 mSnapshot = (Computer) snapshot; 112 } 113 114 @CallSuper 115 @Override close()116 public void close() { 117 mClosed = true; 118 mSnapshot = null; 119 // TODO: Recycle snapshots? 120 } 121 122 @CallSuper checkClosed()123 protected void checkClosed() { 124 if (mClosed) { 125 throw new IllegalStateException("Snapshot already closed"); 126 } 127 } 128 } 129 130 private static class UnfilteredSnapshotImpl extends BaseSnapshotImpl implements 131 UnfilteredSnapshot { 132 133 @Nullable 134 private Map<String, PackageState> mCachedUnmodifiablePackageStates; 135 136 @Nullable 137 private Map<String, SharedUserApi> mCachedUnmodifiableSharedUsers; 138 139 @Nullable 140 private Map<String, PackageState> mCachedUnmodifiableDisabledSystemPackageStates; 141 UnfilteredSnapshotImpl(@onNull PackageDataSnapshot snapshot)142 private UnfilteredSnapshotImpl(@NonNull PackageDataSnapshot snapshot) { 143 super(snapshot); 144 } 145 146 @Override filtered(int callingUid, @NonNull UserHandle user)147 public FilteredSnapshot filtered(int callingUid, @NonNull UserHandle user) { 148 return new FilteredSnapshotImpl(callingUid, user, mSnapshot, this); 149 } 150 151 @SuppressWarnings("RedundantSuppression") 152 @NonNull 153 @Override getPackageStates()154 public Map<String, PackageState> getPackageStates() { 155 checkClosed(); 156 157 if (mCachedUnmodifiablePackageStates == null) { 158 mCachedUnmodifiablePackageStates = 159 Collections.unmodifiableMap(mSnapshot.getPackageStates()); 160 } 161 return mCachedUnmodifiablePackageStates; 162 } 163 164 @SuppressWarnings("RedundantSuppression") 165 @NonNull 166 @Override getSharedUsers()167 public Map<String, SharedUserApi> getSharedUsers() { 168 checkClosed(); 169 170 if (mCachedUnmodifiableSharedUsers == null) { 171 mCachedUnmodifiableSharedUsers = 172 Collections.unmodifiableMap(mSnapshot.getSharedUsers()); 173 } 174 return mCachedUnmodifiableSharedUsers; 175 } 176 177 @SuppressWarnings("RedundantSuppression") 178 @NonNull 179 @Override getDisabledSystemPackageStates()180 public Map<String, PackageState> getDisabledSystemPackageStates() { 181 checkClosed(); 182 183 if (mCachedUnmodifiableDisabledSystemPackageStates == null) { 184 mCachedUnmodifiableDisabledSystemPackageStates = 185 Collections.unmodifiableMap(mSnapshot.getDisabledSystemPackageStates()); 186 } 187 return mCachedUnmodifiableDisabledSystemPackageStates; 188 } 189 190 @Override close()191 public void close() { 192 super.close(); 193 mCachedUnmodifiablePackageStates = null; 194 mCachedUnmodifiableDisabledSystemPackageStates = null; 195 } 196 } 197 198 private static class FilteredSnapshotImpl extends BaseSnapshotImpl implements 199 FilteredSnapshot { 200 201 private final int mCallingUid; 202 203 @UserIdInt 204 private final int mUserId; 205 206 @Nullable 207 private Map<String, PackageState> mFilteredPackageStates; 208 209 @Nullable 210 private final UnfilteredSnapshotImpl mParentSnapshot; 211 FilteredSnapshotImpl(int callingUid, @NonNull UserHandle user, @NonNull PackageDataSnapshot snapshot, @Nullable UnfilteredSnapshotImpl parentSnapshot)212 private FilteredSnapshotImpl(int callingUid, @NonNull UserHandle user, 213 @NonNull PackageDataSnapshot snapshot, 214 @Nullable UnfilteredSnapshotImpl parentSnapshot) { 215 super(snapshot); 216 mCallingUid = callingUid; 217 mUserId = user.getIdentifier(); 218 mParentSnapshot = parentSnapshot; 219 } 220 221 @Override checkClosed()222 protected void checkClosed() { 223 if (mParentSnapshot != null) { 224 mParentSnapshot.checkClosed(); 225 } 226 227 super.checkClosed(); 228 } 229 230 @Override close()231 public void close() { 232 super.close(); 233 mFilteredPackageStates = null; 234 } 235 236 @Nullable 237 @Override getPackageState(@onNull String packageName)238 public PackageState getPackageState(@NonNull String packageName) { 239 checkClosed(); 240 return mSnapshot.getPackageStateFiltered(packageName, mCallingUid, mUserId); 241 } 242 243 @NonNull 244 @Override getPackageStates()245 public Map<String, PackageState> getPackageStates() { 246 checkClosed(); 247 248 if (mFilteredPackageStates == null) { 249 var packageStates = mSnapshot.getPackageStates(); 250 var filteredPackageStates = new ArrayMap<String, PackageState>(); 251 for (int index = 0, size = packageStates.size(); index < size; index++) { 252 var packageState = packageStates.valueAt(index); 253 if (!mSnapshot.shouldFilterApplication(packageState, mCallingUid, mUserId)) { 254 filteredPackageStates.put(packageStates.keyAt(index), packageState); 255 } 256 } 257 mFilteredPackageStates = Collections.unmodifiableMap(filteredPackageStates); 258 } 259 260 return mFilteredPackageStates; 261 } 262 } 263 } 264