diff options
| -rw-r--r-- | services/core/java/com/android/server/pinner/PinRangeSource.java | 27 | ||||
| -rw-r--r-- | services/core/java/com/android/server/pinner/PinRangeSourceStatic.java | 37 | ||||
| -rw-r--r-- | services/core/java/com/android/server/pinner/PinRangeSourceStream.java | 43 | ||||
| -rw-r--r-- | services/core/java/com/android/server/pinner/PinnedFile.java | 61 | ||||
| -rw-r--r-- | services/core/java/com/android/server/pinner/PinnerService.java (renamed from services/core/java/com/android/server/PinnerService.java) | 326 | ||||
| -rw-r--r-- | services/core/java/com/android/server/pinner/PinnerUtils.java | 75 | ||||
| -rw-r--r-- | services/core/java/com/android/server/pm/DexOptHelper.java | 2 | ||||
| -rw-r--r-- | services/core/java/com/android/server/stats/pull/StatsPullAtomService.java | 4 | ||||
| -rw-r--r-- | services/core/java/com/android/server/webkit/SystemImpl.java | 5 | ||||
| -rw-r--r-- | services/java/com/android/server/SystemServer.java | 1 | ||||
| -rw-r--r-- | services/tests/servicestests/src/com/android/server/PinnerServiceTest.java | 10 |
11 files changed, 343 insertions, 248 deletions
diff --git a/services/core/java/com/android/server/pinner/PinRangeSource.java b/services/core/java/com/android/server/pinner/PinRangeSource.java new file mode 100644 index 000000000000..5f9641122294 --- /dev/null +++ b/services/core/java/com/android/server/pinner/PinRangeSource.java @@ -0,0 +1,27 @@ +/* + * Copyright (C) 2024 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 com.android.server.pinner; + +/* package */ abstract class PinRangeSource { + /** + * Retrieve a range to pin. + * + * @param outPinRange Receives the pin region + * @return True if we filled in outPinRange or false if we're out of pin entries + */ + abstract boolean read(PinnerService.PinRange outPinRange); +}
\ No newline at end of file diff --git a/services/core/java/com/android/server/pinner/PinRangeSourceStatic.java b/services/core/java/com/android/server/pinner/PinRangeSourceStatic.java new file mode 100644 index 000000000000..d6fc48790883 --- /dev/null +++ b/services/core/java/com/android/server/pinner/PinRangeSourceStatic.java @@ -0,0 +1,37 @@ +/* + * Copyright (C) 2024 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 com.android.server.pinner; + +/* package */ class PinRangeSourceStatic extends PinRangeSource { + private final int mPinStart; + private final int mPinLength; + private boolean mDone = false; + + PinRangeSourceStatic(int pinStart, int pinLength) { + mPinStart = pinStart; + mPinLength = pinLength; + } + + @Override + boolean read(PinnerService.PinRange outPinRange) { + outPinRange.start = mPinStart; + outPinRange.length = mPinLength; + boolean done = mDone; + mDone = true; + return !done; + } +}
\ No newline at end of file diff --git a/services/core/java/com/android/server/pinner/PinRangeSourceStream.java b/services/core/java/com/android/server/pinner/PinRangeSourceStream.java new file mode 100644 index 000000000000..79900b9de463 --- /dev/null +++ b/services/core/java/com/android/server/pinner/PinRangeSourceStream.java @@ -0,0 +1,43 @@ +/* + * Copyright (C) 2024 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 com.android.server.pinner; + +import java.io.DataInputStream; +import java.io.IOException; +import java.io.InputStream; + +/* package */ final class PinRangeSourceStream extends PinRangeSource { + private final DataInputStream mStream; + private boolean mDone = false; + + PinRangeSourceStream(InputStream stream) { + mStream = new DataInputStream(stream); + } + + @Override + boolean read(PinnerService.PinRange outPinRange) { + if (!mDone) { + try { + outPinRange.start = mStream.readInt(); + outPinRange.length = mStream.readInt(); + } catch (IOException ex) { + mDone = true; + } + } + return !mDone; + } +}
\ No newline at end of file diff --git a/services/core/java/com/android/server/pinner/PinnedFile.java b/services/core/java/com/android/server/pinner/PinnedFile.java new file mode 100644 index 000000000000..a8de344d10af --- /dev/null +++ b/services/core/java/com/android/server/pinner/PinnedFile.java @@ -0,0 +1,61 @@ +/* + * Copyright (C) 2024 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 com.android.server.pinner; + +import com.android.internal.annotations.VisibleForTesting; + +import java.util.ArrayList; + +@VisibleForTesting +public final class PinnedFile implements AutoCloseable { + private long mAddress; + final long mapSize; + final String fileName; + public final long bytesPinned; + + // Whether this file was pinned using a pinlist + boolean used_pinlist; + + // User defined group name for pinner accounting + String groupName = ""; + ArrayList<PinnedFile> pinnedDeps = new ArrayList<>(); + + public PinnedFile(long address, long mapSize, String fileName, long bytesPinned) { + mAddress = address; + this.mapSize = mapSize; + this.fileName = fileName; + this.bytesPinned = bytesPinned; + } + + @Override + public void close() { + if (mAddress >= 0) { + PinnerUtils.safeMunmap(mAddress, mapSize); + mAddress = -1; + } + for (PinnedFile dep : pinnedDeps) { + if (dep != null) { + dep.close(); + } + } + } + + @Override + public void finalize() { + close(); + } +}
\ No newline at end of file diff --git a/services/core/java/com/android/server/PinnerService.java b/services/core/java/com/android/server/pinner/PinnerService.java index 596779d0415b..d7ac5203ff53 100644 --- a/services/core/java/com/android/server/PinnerService.java +++ b/services/core/java/com/android/server/pinner/PinnerService.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2023 The Android Open Source Project + * Copyright (C) 2024 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. @@ -14,7 +14,7 @@ * limitations under the License. */ -package com.android.server; +package com.android.server.pinner; import static android.app.ActivityManager.UID_OBSERVER_ACTIVE; import static android.app.ActivityManager.UID_OBSERVER_GONE; @@ -73,13 +73,13 @@ import com.android.internal.app.ResolverActivity; import com.android.internal.os.BackgroundThread; import com.android.internal.util.DumpUtils; import com.android.internal.util.function.pooled.PooledLambda; +import com.android.server.LocalServices; +import com.android.server.SystemService; import com.android.server.wm.ActivityTaskManagerInternal; import dalvik.system.DexFile; import dalvik.system.VMRuntime; -import java.io.Closeable; -import java.io.DataInputStream; import java.io.FileDescriptor; import java.io.FileOutputStream; import java.io.IOException; @@ -111,8 +111,7 @@ public final class PinnerService extends SystemService { private static final String PIN_META_FILENAME = "pinlist.meta"; private static final int PAGE_SIZE = (int) Os.sysconf(OsConstants._SC_PAGESIZE); private static final int MATCH_FLAGS = PackageManager.MATCH_DEFAULT_ONLY - | PackageManager.MATCH_DIRECT_BOOT_AWARE - | PackageManager.MATCH_DIRECT_BOOT_UNAWARE; + | PackageManager.MATCH_DIRECT_BOOT_AWARE | PackageManager.MATCH_DIRECT_BOOT_UNAWARE; private static final int KEY_CAMERA = 0; private static final int KEY_HOME = 1; @@ -142,7 +141,8 @@ public final class PinnerService extends SystemService { private final UserManager mUserManager; /** The list of the statically pinned files. */ - @GuardedBy("this") private final ArrayMap<String, PinnedFile> mPinnedFiles = new ArrayMap<>(); + @GuardedBy("this") + private final ArrayMap<String, PinnedFile> mPinnedFiles = new ArrayMap<>(); /** The list of the pinned apps. This is a map from {@link AppKey} to a pinned app. */ @GuardedBy("this") @@ -162,8 +162,8 @@ public final class PinnerService extends SystemService { /** * A set of {@link AppKey} that are configured to be pinned. */ - @GuardedBy("this") - private ArraySet<Integer> mPinKeys; + @GuardedBy("this") private + ArraySet<Integer> mPinKeys; // Note that we don't use the `_BOOT` namespace for anonymous pinnings, as we want // them to be responsive to dynamic flag changes for experimentation. @@ -198,8 +198,8 @@ public final class PinnerService extends SystemService { private final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { - // If an app has updated, update pinned files accordingly. - if (Intent.ACTION_PACKAGE_REPLACED.equals(intent.getAction())) { + // If an app has updated, update pinned files accordingly. + if (Intent.ACTION_PACKAGE_REPLACED.equals(intent.getAction())) { Uri packageUri = intent.getData(); String packageName = packageUri.getSchemeSpecificPart(); ArraySet<String> updatedPackages = new ArraySet<>(); @@ -222,7 +222,7 @@ public final class PinnerService extends SystemService { /** Utility class for testing. */ @VisibleForTesting - static class Injector { + public static class Injector { protected DeviceConfigInterface getDeviceConfigInterface() { return DeviceConfigInterface.REAL; } @@ -242,7 +242,7 @@ public final class PinnerService extends SystemService { } @VisibleForTesting - PinnerService(Context context, Injector injector) { + public PinnerService(Context context, Injector injector) { super(context); mContext = context; @@ -276,10 +276,8 @@ public final class PinnerService extends SystemService { registerUidListener(); registerUserSetupCompleteListener(); - mDeviceConfigInterface.addOnPropertiesChangedListener( - DEVICE_CONFIG_NAMESPACE_ANON_SIZE, - new HandlerExecutor(mPinnerHandler), - mDeviceConfigAnonSizeListener); + mDeviceConfigInterface.addOnPropertiesChangedListener(DEVICE_CONFIG_NAMESPACE_ANON_SIZE, + new HandlerExecutor(mPinnerHandler), mDeviceConfigAnonSizeListener); } @Override @@ -377,7 +375,7 @@ public final class PinnerService extends SystemService { private void handlePinOnStart() { // Files to pin come from the overlay and can be specified per-device config String[] filesToPin = mContext.getResources().getStringArray( - com.android.internal.R.array.config_defaultPinnerServiceFiles); + com.android.internal.R.array.config_defaultPinnerServiceFiles); // Continue trying to pin each file even if we fail to pin some of them for (String fileToPin : filesToPin) { pinFile(fileToPin, Integer.MAX_VALUE, /*appInfo=*/null, /*groupName=*/SYSTEM_GROUP_NAME, @@ -393,10 +391,9 @@ public final class PinnerService extends SystemService { * regular home app. */ private void registerUserSetupCompleteListener() { - Uri userSetupCompleteUri = Settings.Secure.getUriFor( - Settings.Secure.USER_SETUP_COMPLETE); - mContext.getContentResolver().registerContentObserver(userSetupCompleteUri, - false, new ContentObserver(null) { + Uri userSetupCompleteUri = Settings.Secure.getUriFor(Settings.Secure.USER_SETUP_COMPLETE); + mContext.getContentResolver().registerContentObserver( + userSetupCompleteUri, false, new ContentObserver(null) { @Override public void onChange(boolean selfChange, Uri uri) { if (userSetupCompleteUri.equals(uri)) { @@ -419,7 +416,7 @@ public final class PinnerService extends SystemService { } @Override - public void onUidActive(int uid) { + public void onUidActive(int uid) { mPinnerHandler.sendMessage(PooledLambda.obtainMessage( PinnerService::handleUidActive, PinnerService.this, uid)); } @@ -433,7 +430,6 @@ public final class PinnerService extends SystemService { updateActiveState(uid, false /* active */); int key; synchronized (this) { - // In case we have a pending repin, repin now. See mPendingRepin for more information. key = mPendingRepin.getOrDefault(uid, -1); if (key == -1) { @@ -501,8 +497,8 @@ public final class PinnerService extends SystemService { private ApplicationInfo getCameraInfo(int userHandle) { Intent cameraIntent = new Intent(MediaStore.INTENT_ACTION_STILL_IMAGE_CAMERA); - ApplicationInfo info = getApplicationInfoForIntent(cameraIntent, userHandle, - false /* defaultToSystemApp */); + ApplicationInfo info = getApplicationInfoForIntent( + cameraIntent, userHandle, false /* defaultToSystemApp */); // If the STILL_IMAGE_CAMERA intent doesn't resolve, try the _SECURE intent. // We don't use _SECURE first because it will never get set on a device @@ -511,16 +507,16 @@ public final class PinnerService extends SystemService { // preference using this intent. if (info == null) { cameraIntent = new Intent(MediaStore.INTENT_ACTION_STILL_IMAGE_CAMERA_SECURE); - info = getApplicationInfoForIntent(cameraIntent, userHandle, - false /* defaultToSystemApp */); + info = getApplicationInfoForIntent( + cameraIntent, userHandle, false /* defaultToSystemApp */); } // If the _SECURE intent doesn't resolve, try the original intent but request // the system app for camera if there was more than one result. if (info == null) { cameraIntent = new Intent(MediaStore.INTENT_ACTION_STILL_IMAGE_CAMERA); - info = getApplicationInfoForIntent(cameraIntent, userHandle, - true /* defaultToSystemApp */); + info = getApplicationInfoForIntent( + cameraIntent, userHandle, true /* defaultToSystemApp */); } return info; } @@ -535,14 +531,14 @@ public final class PinnerService extends SystemService { return getApplicationInfoForIntent(intent, userHandle, true); } - private ApplicationInfo getApplicationInfoForIntent(Intent intent, int userHandle, - boolean defaultToSystemApp) { + private ApplicationInfo getApplicationInfoForIntent( + Intent intent, int userHandle, boolean defaultToSystemApp) { if (intent == null) { return null; } - ResolveInfo resolveInfo = mContext.getPackageManager().resolveActivityAsUser(intent, - MATCH_FLAGS, userHandle); + ResolveInfo resolveInfo = + mContext.getPackageManager().resolveActivityAsUser(intent, MATCH_FLAGS, userHandle); // If this intent can resolve to only one app, choose that one. // Otherwise, if we've requested to default to the system app, return it; @@ -557,12 +553,11 @@ public final class PinnerService extends SystemService { } if (defaultToSystemApp) { - List<ResolveInfo> infoList = mContext.getPackageManager() - .queryIntentActivitiesAsUser(intent, MATCH_FLAGS, userHandle); + List<ResolveInfo> infoList = mContext.getPackageManager().queryIntentActivitiesAsUser( + intent, MATCH_FLAGS, userHandle); ApplicationInfo systemAppInfo = null; for (ResolveInfo info : infoList) { - if ((info.activityInfo.applicationInfo.flags - & ApplicationInfo.FLAG_SYSTEM) != 0) { + if ((info.activityInfo.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0) { if (systemAppInfo == null) { systemAppInfo = info.activityInfo.applicationInfo; } else { @@ -578,13 +573,13 @@ public final class PinnerService extends SystemService { } private void sendPinAppsMessage(int userHandle) { - mPinnerHandler.sendMessage(PooledLambda.obtainMessage(PinnerService::pinApps, this, - userHandle)); + mPinnerHandler.sendMessage( + PooledLambda.obtainMessage(PinnerService::pinApps, this, userHandle)); } private void sendPinAppsWithUpdatedKeysMessage(int userHandle) { - mPinnerHandler.sendMessage(PooledLambda.obtainMessage(PinnerService::pinAppsWithUpdatedKeys, - this, userHandle)); + mPinnerHandler.sendMessage(PooledLambda.obtainMessage( + PinnerService::pinAppsWithUpdatedKeys, this, userHandle)); } private void sendUnpinAppsMessage() { mPinnerHandler.sendMessage(PooledLambda.obtainMessage(PinnerService::unpinApps, this)); @@ -596,8 +591,7 @@ public final class PinnerService extends SystemService { // phenotype property is not set. boolean shouldPinCamera = mConfiguredToPinCamera && mDeviceConfigInterface.getBoolean(DeviceConfig.NAMESPACE_RUNTIME_NATIVE_BOOT, - "pin_camera", - SystemProperties.getBoolean("pinner.pin_camera", true)); + "pin_camera", SystemProperties.getBoolean("pinner.pin_camera", true)); if (shouldPinCamera) { pinKeys.add(KEY_CAMERA); } else if (DEBUG) { @@ -636,8 +630,9 @@ public final class PinnerService extends SystemService { synchronized (this) { // This code path demands preceding unpinApps() call. if (!mPinnedApps.isEmpty()) { - Slog.e(TAG, "Attempted to update a list of apps, " - + "but apps were already pinned. Skipping."); + Slog.e(TAG, + "Attempted to update a list of apps, " + + "but apps were already pinned. Skipping."); return; } @@ -656,8 +651,8 @@ public final class PinnerService extends SystemService { * @see #pinApp(int, int, boolean) */ private void sendPinAppMessage(int key, int userHandle, boolean force) { - mPinnerHandler.sendMessage(PooledLambda.obtainMessage(PinnerService::pinApp, this, - key, userHandle, force)); + mPinnerHandler.sendMessage( + PooledLambda.obtainMessage(PinnerService::pinApp, this, key, userHandle, force)); } /** @@ -692,9 +687,7 @@ public final class PinnerService extends SystemService { private int getUidForKey(@AppKey int key) { synchronized (this) { PinnedApp existing = mPinnedApps.get(key); - return existing != null && existing.active - ? existing.uid - : -1; + return existing != null && existing.active ? existing.uid : -1; } } @@ -737,11 +730,8 @@ public final class PinnerService extends SystemService { * Handle any changes in the anon region pinner config. */ private void refreshPinAnonConfig() { - long newPinAnonSize = - mDeviceConfigInterface.getLong( - DEVICE_CONFIG_NAMESPACE_ANON_SIZE, - DEVICE_CONFIG_KEY_ANON_SIZE, - DEFAULT_ANON_SIZE); + long newPinAnonSize = mDeviceConfigInterface.getLong( + DEVICE_CONFIG_NAMESPACE_ANON_SIZE, DEVICE_CONFIG_KEY_ANON_SIZE, DEFAULT_ANON_SIZE); newPinAnonSize = Math.max(0, Math.min(newPinAnonSize, MAX_ANON_SIZE)); if (newPinAnonSize != mPinAnonSize) { mPinAnonSize = newPinAnonSize; @@ -775,10 +765,9 @@ public final class PinnerService extends SystemService { try { // Map as SHARED to avoid changing rss.anon for system_server (per /proc/*/status). // The mapping is visible in other rss metrics, and as private dirty in smaps/meminfo. - address = Os.mmap(0, alignedPinSize, - OsConstants.PROT_READ | OsConstants.PROT_WRITE, - OsConstants.MAP_SHARED | OsConstants.MAP_ANONYMOUS, - new FileDescriptor(), /*offset=*/0); + address = Os.mmap(0, alignedPinSize, OsConstants.PROT_READ | OsConstants.PROT_WRITE, + OsConstants.MAP_SHARED | OsConstants.MAP_ANONYMOUS, new FileDescriptor(), + /*offset=*/0); Unsafe tempUnsafe = null; Class<sun.misc.Unsafe> clazz = sun.misc.Unsafe.class; @@ -804,14 +793,14 @@ public final class PinnerService extends SystemService { return; } finally { if (address >= 0) { - safeMunmap(address, alignedPinSize); + PinnerUtils.safeMunmap(address, alignedPinSize); } } } private void unpinAnonRegion() { if (mPinAnonAddress != 0) { - safeMunmap(mPinAnonAddress, mCurrentlyPinnedAnonSize); + PinnerUtils.safeMunmap(mPinAnonAddress, mCurrentlyPinnedAnonSize); } mPinAnonAddress = 0; mCurrentlyPinnedAnonSize = 0; @@ -857,7 +846,6 @@ public final class PinnerService extends SystemService { mPinnedApps.put(key, pinnedApp); } - // pin APK final int pinSizeLimit = getSizeLimitForKey(key); List<String> apks = new ArrayList<>(); @@ -871,7 +859,7 @@ public final class PinnerService extends SystemService { long apkPinSizeLimit = pinSizeLimit; - for (String apk: apks) { + for (String apk : apks) { if (apkPinSizeLimit <= 0) { Slog.w(TAG, "Reached to the pin size limit. Skipping: " + apk); // Continue instead of break to print all skipped APK names. @@ -915,7 +903,7 @@ public final class PinnerService extends SystemService { @Nullable ApplicationInfo appInfo, @Nullable String groupName, boolean pinOptimizedDeps) { PinnedFile existingPin; - synchronized(this) { + synchronized (this) { existingPin = mPinnedFiles.get(fileToPin); } if (existingPin != null) { @@ -1021,7 +1009,8 @@ public final class PinnerService extends SystemService { return bytesPinned; } - /** mlock length bytes of fileToPin in memory + /** + * mlock length bytes of fileToPin in memory * * If attemptPinIntrospection is true, then treat the file to pin as a zip file and * look for a "pinlist.meta" file in the archive root directory. The structure of this @@ -1083,8 +1072,8 @@ public final class PinnerService extends SystemService { } return pinnedFile; } finally { - safeClose(pinRangeStream); - safeClose(fileAsZip); // Also closes any streams we've opened + PinnerUtils.safeClose(pinRangeStream); + PinnerUtils.safeClose(fileAsZip); // Also closes any streams we've opened } } @@ -1097,11 +1086,8 @@ public final class PinnerService extends SystemService { try { zip = new ZipFile(fileName); } catch (IOException ex) { - Slog.w(TAG, - String.format( - "could not open \"%s\" as zip: pinning as blob", - fileName), - ex); + Slog.w(TAG, String.format("could not open \"%s\" as zip: pinning as blob", fileName), + ex); } return zip; } @@ -1141,9 +1127,9 @@ public final class PinnerService extends SystemService { pinMetaStream = zipFile.getInputStream(pinMetaEntry); } catch (IOException ex) { Slog.w(TAG, - String.format("error reading pin metadata \"%s\": pinning as blob", - fileName), - ex); + String.format( + "error reading pin metadata \"%s\": pinning as blob", fileName), + ex); } } else { Slog.w(TAG, @@ -1153,57 +1139,6 @@ public final class PinnerService extends SystemService { return pinMetaStream; } - private static abstract class PinRangeSource { - /** Retrive a range to pin. - * - * @param outPinRange Receives the pin region - * @return True if we filled in outPinRange or false if we're out of pin entries - */ - abstract boolean read(PinRange outPinRange); - } - - private static final class PinRangeSourceStatic extends PinRangeSource { - private final int mPinStart; - private final int mPinLength; - private boolean mDone = false; - - PinRangeSourceStatic(int pinStart, int pinLength) { - mPinStart = pinStart; - mPinLength = pinLength; - } - - @Override - boolean read(PinRange outPinRange) { - outPinRange.start = mPinStart; - outPinRange.length = mPinLength; - boolean done = mDone; - mDone = true; - return !done; - } - } - - private static final class PinRangeSourceStream extends PinRangeSource { - private final DataInputStream mStream; - private boolean mDone = false; - - PinRangeSourceStream(InputStream stream) { - mStream = new DataInputStream(stream); - } - - @Override - boolean read(PinRange outPinRange) { - if (!mDone) { - try { - outPinRange.start = mStream.readInt(); - outPinRange.length = mStream.readInt(); - } catch (IOException ex) { - mDone = true; - } - } - return !mDone; - } - } - /** * Helper for pinFile. * @@ -1223,10 +1158,8 @@ public final class PinnerService extends SystemService { int openFlags = (OsConstants.O_RDONLY | OsConstants.O_CLOEXEC); fd = Os.open(fileToPin, openFlags, 0); mapSize = (int) Math.min(Os.fstat(fd).st_size, Integer.MAX_VALUE); - address = Os.mmap(0, mapSize, - OsConstants.PROT_READ, - OsConstants.MAP_SHARED, - fd, /*offset=*/0); + address = Os.mmap( + 0, mapSize, OsConstants.PROT_READ, OsConstants.MAP_SHARED, fd, /*offset=*/0); PinRange pinRange = new PinRange(); long bytesPinned = 0; @@ -1239,8 +1172,8 @@ public final class PinnerService extends SystemService { while (bytesPinned < maxBytesToPin && pinRangeSource.read(pinRange)) { long pinStart = pinRange.start; long pinLength = pinRange.length; - pinStart = clamp(0, pinStart, mapSize); - pinLength = clamp(0, pinLength, mapSize - pinStart); + pinStart = PinnerUtils.clamp(0, pinStart, mapSize); + pinLength = PinnerUtils.clamp(0, pinLength, mapSize - pinStart); pinLength = Math.min(maxBytesToPin - bytesPinned, pinLength); // mlock doesn't require the region to be page-aligned, but we snap the @@ -1255,14 +1188,13 @@ public final class PinnerService extends SystemService { if (pinLength % PAGE_SIZE != 0) { pinLength += PAGE_SIZE - pinLength % PAGE_SIZE; } - pinLength = clamp(0, pinLength, maxBytesToPin - bytesPinned); + pinLength = PinnerUtils.clamp(0, pinLength, maxBytesToPin - bytesPinned); if (pinLength > 0) { if (DEBUG) { Slog.d(TAG, - String.format( - "pinning at %s %s bytes of %s", - pinStart, pinLength, fileToPin)); + String.format("pinning at %s %s bytes of %s", pinStart, pinLength, + fileToPin)); } Os.mlock(address + pinStart, pinLength); } @@ -1270,15 +1202,15 @@ public final class PinnerService extends SystemService { } PinnedFile pinnedFile = new PinnedFile(address, mapSize, fileToPin, bytesPinned); - address = -1; // Ownership transferred + address = -1; // Ownership transferred return pinnedFile; } catch (ErrnoException ex) { Slog.e(TAG, "Could not pin file " + fileToPin, ex); return null; } finally { - safeClose(fd); + PinnerUtils.safeClose(fd); if (address >= 0) { - safeMunmap(address, mapSize); + PinnerUtils.safeMunmap(address, mapSize); } } } @@ -1339,54 +1271,10 @@ public final class PinnerService extends SystemService { return unpinnedBytes; } - private static long clamp(long min, long value, long max) { - return Math.max(min, Math.min(value, max)); - } - - private static void safeMunmap(long address, long mapSize) { - try { - Os.munmap(address, mapSize); - } catch (ErrnoException ex) { - Slog.w(TAG, "ignoring error in unmap", ex); - } - } - - /** - * Close FD, swallowing irrelevant errors. - */ - private static void safeClose(@Nullable FileDescriptor fd) { - if (fd != null && fd.valid()) { - try { - Os.close(fd); - } catch (ErrnoException ex) { - // Swallow the exception: non-EBADF errors in close(2) - // indicate deferred paging write errors, which we - // don't care about here. The underlying file - // descriptor is always closed. - if (ex.errno == OsConstants.EBADF) { - throw new AssertionError(ex); - } - } - } - } - - /** - * Close closeable thing, swallowing errors. - */ - private static void safeClose(@Nullable Closeable thing) { - if (thing != null) { - try { - thing.close(); - } catch (IOException ex) { - Slog.w(TAG, "ignoring error closing resource: " + thing, ex); - } - } - } - public List<PinnedFileStat> getPinnerStats() { ArrayList<PinnedFileStat> stats = new ArrayList<>(); Collection<PinnedFile> pinnedFiles; - synchronized(this) { + synchronized (this) { pinnedFiles = mPinnedFiles.values(); } for (PinnedFile pf : pinnedFiles) { @@ -1394,8 +1282,8 @@ public final class PinnerService extends SystemService { stats.add(stat); } if (mCurrentlyPinnedAnonSize > 0) { - stats.add(new PinnedFileStat(ANON_REGION_STAT_NAME, - mCurrentlyPinnedAnonSize, ANON_REGION_STAT_NAME)); + stats.add(new PinnedFileStat( + ANON_REGION_STAT_NAME, mCurrentlyPinnedAnonSize, ANON_REGION_STAT_NAME)); } return stats; } @@ -1403,7 +1291,8 @@ public final class PinnerService extends SystemService { public final class BinderService extends IPinnerService.Stub { @Override protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) { - if (!DumpUtils.checkDumpPermission(mContext, TAG, pw)) return; + if (!DumpUtils.checkDumpPermission(mContext, TAG, pw)) + return; HashSet<PinnedFile> shownPins = new HashSet<>(); HashSet<String> shownGroups = new HashSet<>(); HashSet<String> groupsToPrint = new HashSet<>(); @@ -1423,8 +1312,10 @@ public final class PinnerService extends SystemService { for (int key : mPinnedApps.keySet()) { PinnedApp app = mPinnedApps.get(key); pw.print(getNameForKey(key)); - pw.print(" uid="); pw.print(app.uid); - pw.print(" active="); pw.print(app.active); + pw.print(" uid="); + pw.print(app.uid); + pw.print(" active="); + pw.print(app.active); if (!app.mFiles.isEmpty()) { shownGroups.add(app.mFiles.getFirst().groupName); @@ -1516,7 +1407,8 @@ public final class PinnerService extends SystemService { if (!mPendingRepin.isEmpty()) { pw.print("Pending repin: "); for (int key : mPendingRepin.values()) { - pw.print(getNameForKey(key)); pw.print(' '); + pw.print(getNameForKey(key)); + pw.print(' '); } pw.println(); } @@ -1550,8 +1442,9 @@ public final class PinnerService extends SystemService { repin(); break; default: - printError(out, String.format( - "Unknown pinner command: %s. Supported commands: repin", command)); + printError(out, + String.format("Unknown pinner command: %s. Supported commands: repin", + command)); resultReceiver.send(-1, null); return; } @@ -1567,46 +1460,6 @@ public final class PinnerService extends SystemService { } } - @VisibleForTesting - public static final class PinnedFile implements AutoCloseable { - private long mAddress; - final long mapSize; - final String fileName; - public final long bytesPinned; - - // Whether this file was pinned using a pinlist - boolean used_pinlist; - - // User defined group name for pinner accounting - String groupName = ""; - ArrayList<PinnedFile> pinnedDeps = new ArrayList<>(); - - PinnedFile(long address, long mapSize, String fileName, long bytesPinned) { - mAddress = address; - this.mapSize = mapSize; - this.fileName = fileName; - this.bytesPinned = bytesPinned; - } - - @Override - public void close() { - if (mAddress >= 0) { - safeMunmap(mAddress, mapSize); - mAddress = -1; - } - for (PinnedFile dep : pinnedDeps) { - if (dep != null) { - dep.close(); - } - } - } - - @Override - public void finalize() { - close(); - } - } - final static class PinRange { int start; int length; @@ -1616,7 +1469,6 @@ public final class PinnerService extends SystemService { * Represents an app that was pinned. */ private final class PinnedApp { - /** * The uid of the package being pinned. This stays constant while the package stays * installed. @@ -1645,11 +1497,9 @@ public final class PinnerService extends SystemService { @Override public void handleMessage(Message msg) { switch (msg.what) { - case PIN_ONSTART_MSG: - { + case PIN_ONSTART_MSG: { handlePinOnStart(); - } - break; + } break; default: super.handleMessage(msg); diff --git a/services/core/java/com/android/server/pinner/PinnerUtils.java b/services/core/java/com/android/server/pinner/PinnerUtils.java new file mode 100644 index 000000000000..a836a83dedab --- /dev/null +++ b/services/core/java/com/android/server/pinner/PinnerUtils.java @@ -0,0 +1,75 @@ +/* + * Copyright (C) 2024 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 com.android.server.pinner; + +import android.annotation.Nullable; +import android.system.ErrnoException; +import android.system.Os; +import android.system.OsConstants; +import android.util.Slog; + +import java.io.Closeable; +import java.io.FileDescriptor; +import java.io.IOException; + +/* package */ final class PinnerUtils { + private static final String TAG = "PinnerUtils"; + + public static long clamp(long min, long value, long max) { + return Math.max(min, Math.min(value, max)); + } + + public static void safeMunmap(long address, long mapSize) { + try { + Os.munmap(address, mapSize); + } catch (ErrnoException ex) { + Slog.w(TAG, "ignoring error in unmap", ex); + } + } + + /** + * Close FD, swallowing irrelevant errors. + */ + public static void safeClose(@Nullable FileDescriptor fd) { + if (fd != null && fd.valid()) { + try { + Os.close(fd); + } catch (ErrnoException ex) { + // Swallow the exception: non-EBADF errors in close(2) + // indicate deferred paging write errors, which we + // don't care about here. The underlying file + // descriptor is always closed. + if (ex.errno == OsConstants.EBADF) { + throw new AssertionError(ex); + } + } + } + } + + /** + * Close closeable thing, swallowing errors. + */ + public static void safeClose(@Nullable Closeable thing) { + if (thing != null) { + try { + thing.close(); + } catch (IOException ex) { + Slog.w(TAG, "ignoring error closing resource: " + thing, ex); + } + } + } +} diff --git a/services/core/java/com/android/server/pm/DexOptHelper.java b/services/core/java/com/android/server/pm/DexOptHelper.java index 9ecc7b9a805d..1569fa0aa8d7 100644 --- a/services/core/java/com/android/server/pm/DexOptHelper.java +++ b/services/core/java/com/android/server/pm/DexOptHelper.java @@ -70,13 +70,13 @@ import com.android.internal.util.FrameworkStatsLog; import com.android.internal.util.IndentingPrintWriter; import com.android.server.LocalManagerRegistry; import com.android.server.LocalServices; -import com.android.server.PinnerService; import com.android.server.art.ArtManagerLocal; import com.android.server.art.DexUseManagerLocal; import com.android.server.art.ReasonMapping; import com.android.server.art.model.ArtFlags; import com.android.server.art.model.DexoptParams; import com.android.server.art.model.DexoptResult; +import com.android.server.pinner.PinnerService; import com.android.server.pm.PackageDexOptimizer.DexOptResult; import com.android.server.pm.dex.DexManager; import com.android.server.pm.dex.DexoptOptions; diff --git a/services/core/java/com/android/server/stats/pull/StatsPullAtomService.java b/services/core/java/com/android/server/stats/pull/StatsPullAtomService.java index b35a0a772ff2..74c1124e1f16 100644 --- a/services/core/java/com/android/server/stats/pull/StatsPullAtomService.java +++ b/services/core/java/com/android/server/stats/pull/StatsPullAtomService.java @@ -216,13 +216,13 @@ import com.android.role.RoleManagerLocal; import com.android.server.BinderCallsStatsService; import com.android.server.LocalManagerRegistry; import com.android.server.LocalServices; -import com.android.server.PinnerService; -import com.android.server.PinnerService.PinnedFileStats; import com.android.server.SystemService; import com.android.server.SystemServiceManager; import com.android.server.am.MemoryStatUtil.MemoryStat; import com.android.server.health.HealthServiceWrapper; import com.android.server.notification.NotificationManagerService; +import com.android.server.pinner.PinnerService; +import com.android.server.pinner.PinnerService.PinnedFileStats; import com.android.server.pm.UserManagerInternal; import com.android.server.power.stats.KernelWakelockReader; import com.android.server.power.stats.KernelWakelockStats; diff --git a/services/core/java/com/android/server/webkit/SystemImpl.java b/services/core/java/com/android/server/webkit/SystemImpl.java index 7e87c716f102..ab5316f46d78 100644 --- a/services/core/java/com/android/server/webkit/SystemImpl.java +++ b/services/core/java/com/android/server/webkit/SystemImpl.java @@ -41,7 +41,8 @@ import android.webkit.WebViewZygote; import com.android.internal.util.XmlUtils; import com.android.server.LocalServices; -import com.android.server.PinnerService; +import com.android.server.pinner.PinnedFile; +import com.android.server.pinner.PinnerService; import org.xmlpull.v1.XmlPullParserException; @@ -318,7 +319,7 @@ public class SystemImpl implements SystemInterface { if (webviewPinQuota <= 0) { break; } - PinnerService.PinnedFile pf = pinnerService.pinFile( + PinnedFile pf = pinnerService.pinFile( apk, webviewPinQuota, appInfo, PIN_GROUP, /*pinOptimizedDeps=*/true); webviewPinQuota -= pf.bytesPinned; } diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java index ab459df1cdf6..3fc2bf7942e3 100644 --- a/services/java/com/android/server/SystemServer.java +++ b/services/java/com/android/server/SystemServer.java @@ -204,6 +204,7 @@ import com.android.server.os.SchedulingPolicyService; import com.android.server.pdb.PersistentDataBlockService; import com.android.server.people.PeopleService; import com.android.server.permission.access.AccessCheckingService; +import com.android.server.pinner.PinnerService; import com.android.server.pm.ApexManager; import com.android.server.pm.ApexSystemServiceInfo; import com.android.server.pm.BackgroundInstallControlService; diff --git a/services/tests/servicestests/src/com/android/server/PinnerServiceTest.java b/services/tests/servicestests/src/com/android/server/PinnerServiceTest.java index bff0170fa505..c18faef2c028 100644 --- a/services/tests/servicestests/src/com/android/server/PinnerServiceTest.java +++ b/services/tests/servicestests/src/com/android/server/PinnerServiceTest.java @@ -33,7 +33,6 @@ import android.os.Handler; import android.os.Looper; import android.platform.test.annotations.DisableFlags; import android.platform.test.annotations.EnableFlags; -import android.platform.test.annotations.DisableFlags; import android.platform.test.flag.junit.SetFlagsRule; import android.provider.DeviceConfig; import android.provider.DeviceConfigInterface; @@ -48,6 +47,8 @@ import androidx.test.filters.SmallTest; import androidx.test.runner.AndroidJUnit4; import com.android.server.flags.Flags; +import com.android.server.pinner.PinnedFile; +import com.android.server.pinner.PinnerService; import com.android.server.testutils.FakeDeviceConfigInterface; import com.android.server.wm.ActivityTaskManagerInternal; @@ -148,10 +149,9 @@ public class PinnerServiceTest { } @Override - protected PinnerService.PinnedFile pinFileInternal(PinnerService service, - String fileToPin, long maxBytesToPin, boolean attemptPinIntrospection) { - return new PinnerService.PinnedFile(-1, - maxBytesToPin, fileToPin, maxBytesToPin); + protected PinnedFile pinFileInternal(PinnerService service, String fileToPin, + long maxBytesToPin, boolean attemptPinIntrospection) { + return new PinnedFile(-1, maxBytesToPin, fileToPin, maxBytesToPin); } }; } |