Loading services/core/java/com/android/server/PinnerService.java +75 −0 Original line number Diff line number Diff line Loading @@ -78,11 +78,14 @@ import java.io.InputStream; import java.io.PrintWriter; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.reflect.Method; import java.util.ArrayList; import java.util.List; import java.util.zip.ZipEntry; import java.util.zip.ZipFile; import sun.misc.Unsafe; /** * <p>PinnerService pins important files for key processes in memory.</p> * <p>Files to pin are specified in the config_defaultPinnerServiceFiles Loading Loading @@ -150,6 +153,11 @@ public final class PinnerService extends SystemService { @GuardedBy("this") private ArraySet<Integer> mPinKeys; private static final long MAX_ANON_SIZE = 2L * (1L << 30); // 2GB private long mPinAnonSize; private long mPinAnonAddress; private long mCurrentlyPinnedAnonSize; // Resource-configured pinner flags; private final boolean mConfiguredToPinCamera; private final boolean mConfiguredToPinHome; Loading Loading @@ -550,6 +558,11 @@ public final class PinnerService extends SystemService { pinKeys.add(KEY_ASSISTANT); } mPinAnonSize = DeviceConfig.getLong(DeviceConfig.NAMESPACE_RUNTIME_NATIVE_BOOT, "pin_anon_size", SystemProperties.getLong("pinner.pin_anon_size", 0)); mPinAnonSize = Math.max(0, Math.min(mPinAnonSize, MAX_ANON_SIZE)); return pinKeys; } Loading Loading @@ -589,6 +602,7 @@ public final class PinnerService extends SystemService { int key = currentPinKeys.valueAt(i); pinApp(key, userHandle, true /* force */); } pinAnonRegion(); } /** Loading Loading @@ -672,6 +686,64 @@ public final class PinnerService extends SystemService { } } /** * Pin an empty anonymous region. This should only be used for ablation experiments. */ private void pinAnonRegion() { if (mPinAnonSize == 0) { return; } long alignedPinSize = mPinAnonSize; if (alignedPinSize % PAGE_SIZE != 0) { alignedPinSize -= alignedPinSize % PAGE_SIZE; Slog.e(TAG, "pinAnonRegion: aligning size to " + alignedPinSize); } if (mPinAnonAddress != 0 && mCurrentlyPinnedAnonSize != alignedPinSize) { unpinAnonRegion(); } long address = 0; try { address = Os.mmap(0, alignedPinSize, OsConstants.PROT_READ | OsConstants.PROT_WRITE, OsConstants.MAP_PRIVATE | OsConstants.MAP_ANONYMOUS, new FileDescriptor(), /*offset=*/0); Unsafe tempUnsafe = null; Class<sun.misc.Unsafe> clazz = sun.misc.Unsafe.class; for (java.lang.reflect.Field f : clazz.getDeclaredFields()) { f.setAccessible(true); Object obj = f.get(null); if (clazz.isInstance(obj)) { tempUnsafe = clazz.cast(obj); } } if (tempUnsafe == null) { throw new Exception("Couldn't get Unsafe"); } Method setMemory = clazz.getMethod("setMemory", long.class, long.class, byte.class); setMemory.invoke(tempUnsafe, address, alignedPinSize, (byte) 1); Os.mlock(address, alignedPinSize); mCurrentlyPinnedAnonSize = alignedPinSize; mPinAnonAddress = address; address = -1; Slog.e(TAG, "pinAnonRegion success, size=" + mCurrentlyPinnedAnonSize); } catch (Exception ex) { Slog.e(TAG, "Could not pin anon region of size " + alignedPinSize, ex); return; } finally { if (address >= 0) { safeMunmap(address, alignedPinSize); } } } private void unpinAnonRegion() { if (mPinAnonAddress != 0) { safeMunmap(mPinAnonAddress, mCurrentlyPinnedAnonSize); } } /** * @return The maximum amount of bytes to be pinned for an app of type {@code key}. */ Loading Loading @@ -1083,6 +1155,9 @@ public final class PinnerService extends SystemService { totalSize += pf.bytesPinned; } } if (mPinAnonAddress != 0) { pw.format("Pinned anon region: %s\n", mCurrentlyPinnedAnonSize); } pw.format("Total size: %s\n", totalSize); pw.println(); if (!mPendingRepin.isEmpty()) { Loading Loading
services/core/java/com/android/server/PinnerService.java +75 −0 Original line number Diff line number Diff line Loading @@ -78,11 +78,14 @@ import java.io.InputStream; import java.io.PrintWriter; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.reflect.Method; import java.util.ArrayList; import java.util.List; import java.util.zip.ZipEntry; import java.util.zip.ZipFile; import sun.misc.Unsafe; /** * <p>PinnerService pins important files for key processes in memory.</p> * <p>Files to pin are specified in the config_defaultPinnerServiceFiles Loading Loading @@ -150,6 +153,11 @@ public final class PinnerService extends SystemService { @GuardedBy("this") private ArraySet<Integer> mPinKeys; private static final long MAX_ANON_SIZE = 2L * (1L << 30); // 2GB private long mPinAnonSize; private long mPinAnonAddress; private long mCurrentlyPinnedAnonSize; // Resource-configured pinner flags; private final boolean mConfiguredToPinCamera; private final boolean mConfiguredToPinHome; Loading Loading @@ -550,6 +558,11 @@ public final class PinnerService extends SystemService { pinKeys.add(KEY_ASSISTANT); } mPinAnonSize = DeviceConfig.getLong(DeviceConfig.NAMESPACE_RUNTIME_NATIVE_BOOT, "pin_anon_size", SystemProperties.getLong("pinner.pin_anon_size", 0)); mPinAnonSize = Math.max(0, Math.min(mPinAnonSize, MAX_ANON_SIZE)); return pinKeys; } Loading Loading @@ -589,6 +602,7 @@ public final class PinnerService extends SystemService { int key = currentPinKeys.valueAt(i); pinApp(key, userHandle, true /* force */); } pinAnonRegion(); } /** Loading Loading @@ -672,6 +686,64 @@ public final class PinnerService extends SystemService { } } /** * Pin an empty anonymous region. This should only be used for ablation experiments. */ private void pinAnonRegion() { if (mPinAnonSize == 0) { return; } long alignedPinSize = mPinAnonSize; if (alignedPinSize % PAGE_SIZE != 0) { alignedPinSize -= alignedPinSize % PAGE_SIZE; Slog.e(TAG, "pinAnonRegion: aligning size to " + alignedPinSize); } if (mPinAnonAddress != 0 && mCurrentlyPinnedAnonSize != alignedPinSize) { unpinAnonRegion(); } long address = 0; try { address = Os.mmap(0, alignedPinSize, OsConstants.PROT_READ | OsConstants.PROT_WRITE, OsConstants.MAP_PRIVATE | OsConstants.MAP_ANONYMOUS, new FileDescriptor(), /*offset=*/0); Unsafe tempUnsafe = null; Class<sun.misc.Unsafe> clazz = sun.misc.Unsafe.class; for (java.lang.reflect.Field f : clazz.getDeclaredFields()) { f.setAccessible(true); Object obj = f.get(null); if (clazz.isInstance(obj)) { tempUnsafe = clazz.cast(obj); } } if (tempUnsafe == null) { throw new Exception("Couldn't get Unsafe"); } Method setMemory = clazz.getMethod("setMemory", long.class, long.class, byte.class); setMemory.invoke(tempUnsafe, address, alignedPinSize, (byte) 1); Os.mlock(address, alignedPinSize); mCurrentlyPinnedAnonSize = alignedPinSize; mPinAnonAddress = address; address = -1; Slog.e(TAG, "pinAnonRegion success, size=" + mCurrentlyPinnedAnonSize); } catch (Exception ex) { Slog.e(TAG, "Could not pin anon region of size " + alignedPinSize, ex); return; } finally { if (address >= 0) { safeMunmap(address, alignedPinSize); } } } private void unpinAnonRegion() { if (mPinAnonAddress != 0) { safeMunmap(mPinAnonAddress, mCurrentlyPinnedAnonSize); } } /** * @return The maximum amount of bytes to be pinned for an app of type {@code key}. */ Loading Loading @@ -1083,6 +1155,9 @@ public final class PinnerService extends SystemService { totalSize += pf.bytesPinned; } } if (mPinAnonAddress != 0) { pw.format("Pinned anon region: %s\n", mCurrentlyPinnedAnonSize); } pw.format("Total size: %s\n", totalSize); pw.println(); if (!mPendingRepin.isEmpty()) { Loading