/*
 * Copyright (C) 2016 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;

import static android.app.ActivityManager.UID_OBSERVER_ACTIVE;
import static android.app.ActivityManager.UID_OBSERVER_GONE;

import android.annotation.IntDef;
import android.annotation.Nullable;

import android.app.ActivityManager;
import android.app.ActivityManagerInternal;
import android.app.IActivityManager;
import android.app.IUidObserver;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.pm.ActivityInfo;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.database.ContentObserver;
import android.net.Uri;
import android.os.Binder;
import android.os.Build;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import android.os.RemoteException;
import android.os.UserHandle;
import android.os.UserManager;
import android.provider.MediaStore;
import android.provider.Settings;
import android.system.ErrnoException;
import android.system.Os;
import android.system.OsConstants;
import android.util.ArrayMap;
import android.util.ArraySet;
import android.util.Slog;

import com.android.internal.annotations.GuardedBy;
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 dalvik.system.DexFile;
import dalvik.system.VMRuntime;

import java.io.FileDescriptor;
import java.io.Closeable;
import java.io.InputStream;
import java.io.DataInputStream;
import java.io.IOException;
import java.io.PrintWriter;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.util.List;
import java.util.ArrayList;

import java.util.zip.ZipFile;
import java.util.zip.ZipEntry;

/**
 * <p>PinnerService pins important files for key processes in memory.</p>
 * <p>Files to pin are specified in the config_defaultPinnerServiceFiles
 * overlay.</p>
 * <p>Pin the default camera application if specified in config_pinnerCameraApp.</p>
 */
public final class PinnerService extends SystemService {
    private static final boolean DEBUG = false;
    private static final String TAG = "PinnerService";

    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;

    private static final int KEY_CAMERA = 0;
    private static final int KEY_HOME = 1;

    private static final int MAX_CAMERA_PIN_SIZE = 80 * (1 << 20); // 80MB max for camera app.
    private static final int MAX_HOME_PIN_SIZE = 6 * (1 << 20); // 6MB max for home app.

    @IntDef({KEY_CAMERA, KEY_HOME})
    @Retention(RetentionPolicy.SOURCE)
    public @interface AppKey {}

    private final Context mContext;
    private final ActivityManagerInternal mAmInternal;
    private final IActivityManager mAm;
    private final UserManager mUserManager;

    /** The list of the statically pinned files. */
    @GuardedBy("this")
    private final ArrayList<PinnedFile> mPinnedFiles = new ArrayList<>();

    /** The list of the pinned apps. This is a map from {@link AppKey} to a pinned app. */
    @GuardedBy("this")
    private final ArrayMap<Integer, PinnedApp> mPinnedApps = new ArrayMap<>();

    /**
     * The list of the pinned apps that need to be repinned as soon as the all processes of a given
     * uid are no longer active. Note that with background dex opt, the new dex/vdex files are only
     * loaded into the processes once it restarts. So in case background dex opt recompiled these
     * files, we still need to keep the old ones pinned until the processes restart.
     * <p>
     * This is a map from uid to {@link AppKey}
     */
    @GuardedBy("this")
    private final ArrayMap<Integer, Integer> mPendingRepin = new ArrayMap<>();

    /**
     * A set of {@link AppKey} that are configured to be pinned.
     */
    private final ArraySet<Integer> mPinKeys = new ArraySet<>();

    private BinderService mBinderService;
    private PinnerHandler mPinnerHandler = null;

    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())) {
                Uri packageUri = intent.getData();
                String packageName = packageUri.getSchemeSpecificPart();
                ArraySet<String> updatedPackages = new ArraySet<>();
                updatedPackages.add(packageName);
                update(updatedPackages, true /* force */);
            }
        }
    };

    public PinnerService(Context context) {
        super(context);

        mContext = context;
        boolean shouldPinCamera = context.getResources().getBoolean(
                com.android.internal.R.bool.config_pinnerCameraApp);
        boolean shouldPinHome = context.getResources().getBoolean(
                com.android.internal.R.bool.config_pinnerHomeApp);
        if (shouldPinCamera) {
            mPinKeys.add(KEY_CAMERA);
        }
        if (shouldPinHome) {
            mPinKeys.add(KEY_HOME);
        }
        mPinnerHandler = new PinnerHandler(BackgroundThread.get().getLooper());

        mAmInternal = LocalServices.getService(ActivityManagerInternal.class);
        mAm = ActivityManager.getService();

        mUserManager = mContext.getSystemService(UserManager.class);

        IntentFilter filter = new IntentFilter();
        filter.addAction(Intent.ACTION_PACKAGE_REPLACED);
        filter.addDataScheme("package");
        mContext.registerReceiver(mBroadcastReceiver, filter);

        registerUidListener();
        registerUserSetupCompleteListener();
    }

    @Override
    public void onStart() {
        if (DEBUG) {
            Slog.i(TAG, "Starting PinnerService");
        }
        mBinderService = new BinderService();
        publishBinderService("pinner", mBinderService);
        publishLocalService(PinnerService.class, this);

        mPinnerHandler.obtainMessage(PinnerHandler.PIN_ONSTART_MSG).sendToTarget();
        sendPinAppsMessage(UserHandle.USER_SYSTEM);
    }

    /**
     * Repin apps on user switch.
     * <p>
     * If more than one user is using the device each user may set a different preference for the
     * individual apps. Make sure that user's preference is pinned into memory.
     */
    @Override
    public void onSwitchUser(int userHandle) {
        if (!mUserManager.isManagedProfile(userHandle)) {
            sendPinAppsMessage(userHandle);
        }
    }

    @Override
    public void onUnlockUser(int userHandle) {
        if (!mUserManager.isManagedProfile(userHandle)) {
            sendPinAppsMessage(userHandle);
        }
    }

    /**
     * Update the currently pinned files.
     * Specifically, this only updates pinning for the apps that need to be pinned.
     * The other files pinned in onStart will not need to be updated.
     */
    public void update(ArraySet<String> updatedPackages, boolean force) {
        int currentUser = ActivityManager.getCurrentUser();
        for (int i = mPinKeys.size() - 1; i >= 0; i--) {
            int key = mPinKeys.valueAt(i);
            ApplicationInfo info = getInfoForKey(key, currentUser);
            if (info != null && updatedPackages.contains(info.packageName)) {
                Slog.i(TAG, "Updating pinned files for " + info.packageName + " force=" + force);
                sendPinAppMessage(key, currentUser, force);
            }
        }
    }

    /**
     * Handler for on start pinning message
     */
    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);
        // Continue trying to pin each file even if we fail to pin some of them
        for (String fileToPin : filesToPin) {
            PinnedFile pf = pinFile(fileToPin,
                                    Integer.MAX_VALUE,
                                    /*attemptPinIntrospection=*/false);
            if (pf == null) {
                Slog.e(TAG, "Failed to pin file = " + fileToPin);
                continue;
            }

            synchronized (this) {
                mPinnedFiles.add(pf);
            }
        }
    }

    /**
     * Registers a listener to repin the home app when user setup is complete, as the home intent
     * initially resolves to setup wizard, but once setup is complete, it will resolve to the
     * regular home app.
     */
    private void registerUserSetupCompleteListener() {
        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)) {
                            sendPinAppMessage(KEY_HOME, ActivityManager.getCurrentUser(),
                                    true /* force */);
                        }
                    }
                }, UserHandle.USER_ALL);
    }

    private void registerUidListener() {
        try {
            mAm.registerUidObserver(new IUidObserver.Stub() {
                @Override
                public void onUidGone(int uid, boolean disabled) throws RemoteException {
                    mPinnerHandler.sendMessage(PooledLambda.obtainMessage(
                            PinnerService::handleUidGone, PinnerService.this, uid));
                }

                @Override
                public void onUidActive(int uid) throws RemoteException {
                    mPinnerHandler.sendMessage(PooledLambda.obtainMessage(
                            PinnerService::handleUidActive, PinnerService.this, uid));
                }

                @Override
                public void onUidIdle(int uid, boolean disabled) throws RemoteException {
                }

                @Override
                public void onUidStateChanged(int uid, int procState, long procStateSeq)
                        throws RemoteException {
                }

                @Override
                public void onUidCachedChanged(int uid, boolean cached) throws RemoteException {
                }
            }, UID_OBSERVER_GONE | UID_OBSERVER_ACTIVE, 0, "system");
        } catch (RemoteException e) {
            Slog.e(TAG, "Failed to register uid observer", e);
        }
    }

    private void handleUidGone(int uid) {
        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) {
                return;
            }
            mPendingRepin.remove(uid);
        }
        pinApp(key, ActivityManager.getCurrentUser(), false /* force */);
    }

    private void handleUidActive(int uid) {
        updateActiveState(uid, true /* active */);
    }

    private void updateActiveState(int uid, boolean active) {
        synchronized (this) {
            for (int i = mPinnedApps.size() - 1; i >= 0; i--) {
                PinnedApp app = mPinnedApps.valueAt(i);
                if (app.uid == uid) {
                    app.active = active;
                }
            }
        }
    }

    private void unpinApp(@AppKey int key) {
        ArrayList<PinnedFile> pinnedAppFiles;
        synchronized (this) {
            PinnedApp app = mPinnedApps.get(key);
            if (app == null) {
                return;
            }
            mPinnedApps.remove(key);
            pinnedAppFiles = new ArrayList<>(app.mFiles);
        }
        for (PinnedFile pinnedFile : pinnedAppFiles) {
            pinnedFile.close();
        }
    }

    private boolean isResolverActivity(ActivityInfo info) {
        return ResolverActivity.class.getName().equals(info.name);
    }

    private ApplicationInfo getCameraInfo(int userHandle) {
        Intent cameraIntent = new Intent(MediaStore.INTENT_ACTION_STILL_IMAGE_CAMERA);
        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
        // without File-based Encryption. But if the user has only set the intent
        // before unlocking their device, we may still be able to identify their
        // preference using this intent.
        if (info == null) {
            cameraIntent = new Intent(MediaStore.INTENT_ACTION_STILL_IMAGE_CAMERA_SECURE);
            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 */);
        }
        return info;
    }

    private ApplicationInfo getHomeInfo(int userHandle) {
        Intent intent = mAmInternal.getHomeIntent();
        return getApplicationInfoForIntent(intent, userHandle, false);
    }

    private ApplicationInfo getApplicationInfoForIntent(Intent intent, int userHandle,
            boolean defaultToSystemApp) {
        if (intent == null) {
            return null;
        }

        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;
        // if we have not requested that default, return null if there's more than one option.
        // If there's more than one system app, return null since we don't know which to pick.
        if (resolveInfo == null) {
            return null;
        }

        if (!isResolverActivity(resolveInfo.activityInfo)) {
            return resolveInfo.activityInfo.applicationInfo;
        }

        if (defaultToSystemApp) {
            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 (systemAppInfo == null) {
                        systemAppInfo = info.activityInfo.applicationInfo;
                    } else {
                        // If there's more than one system app, return null due to ambiguity.
                        return null;
                    }
                }
            }
            return systemAppInfo;
        }

        return null;
    }

    private void sendPinAppsMessage(int userHandle) {
        mPinnerHandler.sendMessage(PooledLambda.obtainMessage(PinnerService::pinApps, this,
                userHandle));
    }

    private void pinApps(int userHandle) {
        for (int i = mPinKeys.size() - 1; i >= 0; i--) {
            int key = mPinKeys.valueAt(i);
            pinApp(key, userHandle, true /* force */);
        }
    }

    /**
     * @see #pinApp(int, int, boolean)
     */
    private void sendPinAppMessage(int key, int userHandle, boolean force) {
        mPinnerHandler.sendMessage(PooledLambda.obtainMessage(PinnerService::pinApp, this,
                key, userHandle, force));
    }

    /**
     * Pins an app of a specific type {@code key}.
     *
     * @param force If false, this will not repin the app if it's currently active. See
     *              {@link #mPendingRepin}.
     */
    private void pinApp(int key, int userHandle, boolean force) {
        int uid = getUidForKey(key);

        // In case the app is currently active, don't repin until next process restart. See
        // mPendingRepin for more information.
        if (!force && uid != -1) {
            synchronized (this) {
                mPendingRepin.put(uid, key);
            }
            return;
        }
        unpinApp(key);
        ApplicationInfo info = getInfoForKey(key, userHandle);
        if (info != null) {
            pinApp(key, info);
        }
    }

    /**
     * Checks whether the pinned package with {@code key} is active or not.

     * @return The uid of the pinned app, or {@code -1} otherwise.
     */
    private int getUidForKey(@AppKey int key) {
        synchronized (this) {
            PinnedApp existing = mPinnedApps.get(key);
            return existing != null && existing.active
                    ? existing.uid
                    : -1;
        }
    }

    /**
     * Retrieves the current application info for the given app type.
     *
     * @param key The app type to retrieve the info for.
     * @param userHandle The user id of the current user.
     */
    private @Nullable ApplicationInfo getInfoForKey(@AppKey int key, int userHandle) {
        switch (key) {
            case KEY_CAMERA:
                return getCameraInfo(userHandle);
            case KEY_HOME:
                return getHomeInfo(userHandle);
            default:
                return null;
        }
    }

    /**
     * @return The app type name for {@code key}.
     */
    private String getNameForKey(@AppKey int key) {
        switch (key) {
            case KEY_CAMERA:
                return "Camera";
            case KEY_HOME:
                return "Home";
            default:
                return null;
        }
    }

    /**
     * @return The maximum amount of bytes to be pinned for an app of type {@code key}.
     */
    private int getSizeLimitForKey(@AppKey int key) {
        switch (key) {
            case KEY_CAMERA:
                return MAX_CAMERA_PIN_SIZE;
            case KEY_HOME:
                return MAX_HOME_PIN_SIZE;
            default:
                return 0;
        }
    }

    /**
     * Pins an application.
     *
     * @param key The key of the app to pin.
     * @param appInfo The corresponding app info.
     */
    private void pinApp(@AppKey int key, @Nullable ApplicationInfo appInfo) {
        if (appInfo == null) {
            return;
        }

        PinnedApp pinnedApp = new PinnedApp(appInfo);
        synchronized (this) {
            mPinnedApps.put(key, pinnedApp);
        }

        // pin APK
        int pinSizeLimit = getSizeLimitForKey(key);
        String apk = appInfo.sourceDir;
        PinnedFile pf = pinFile(apk, pinSizeLimit, /*attemptPinIntrospection=*/true);
        if (pf == null) {
            Slog.e(TAG, "Failed to pin " + apk);
            return;
        }
        if (DEBUG) {
            Slog.i(TAG, "Pinned " + pf.fileName);
        }
        synchronized (this) {
            pinnedApp.mFiles.add(pf);
        }

        // determine the ABI from either ApplicationInfo or Build
        String arch = "arm";
        if (appInfo.primaryCpuAbi != null) {
            if (VMRuntime.is64BitAbi(appInfo.primaryCpuAbi)) {
                arch = arch + "64";
            }
        } else {
            if (VMRuntime.is64BitAbi(Build.SUPPORTED_ABIS[0])) {
                arch = arch + "64";
            }
        }

        // get the path to the odex or oat file
        String baseCodePath = appInfo.getBaseCodePath();
        String[] files = null;
        try {
            files = DexFile.getDexFileOutputPaths(baseCodePath, arch);
        } catch (IOException ioe) {}
        if (files == null) {
            return;
        }

        //not pinning the oat/odex is not a fatal error
        for (String file : files) {
            pf = pinFile(file, pinSizeLimit, /*attemptPinIntrospection=*/false);
            if (pf != null) {
                synchronized (this) {
                    pinnedApp.mFiles.add(pf);
                }
                if (DEBUG) {
                    Slog.i(TAG, "Pinned " + pf.fileName);
                }
            }
        }
    }

    /** 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
     * file is a PINLIST_META as described below:
     *
     * <pre>
     *   PINLIST_META: PIN_RANGE*
     *   PIN_RANGE: PIN_START PIN_LENGTH
     *   PIN_START: big endian i32: offset in bytes of pin region from file start
     *   PIN_LENGTH: big endian i32: length of pin region in bytes
     * </pre>
     *
     * (We use big endian because that's what DataInputStream is hardcoded to use.)
     *
     * If attemptPinIntrospection is false, then we use a single implicit PIN_RANGE of (0,
     * maxBytesToPin); that is, we attempt to pin the first maxBytesToPin bytes of the file.
     *
     * After we open a file, we march through the list of pin ranges and attempt to pin
     * each one, stopping after we've pinned maxBytesToPin bytes. (We may truncate the last
     * pinned range to fit.)  In this way, by choosing to emit certain PIN_RANGE pairs
     * before others, file generators can express pins in priority order, making most
     * effective use of the pinned-page quota.
     *
     * N.B. Each PIN_RANGE is clamped to the actual bounds of the file; all inputs have a
     * meaningful interpretation. Also, a range locking a single byte of a page locks the
     * whole page. Any truncated PIN_RANGE at EOF is ignored. Overlapping pinned entries
     * are legal, but each pin of a byte counts toward the pin quota regardless of whether
     * that byte has already been pinned, so the generator of PINLIST_META ought to ensure
     * that ranges are non-overlapping.
     *
     * @param fileToPin Path to file to pin
     * @param maxBytesToPin Maximum number of bytes to pin
     * @param attemptPinIntrospection If true, try to open file as a
     *   zip in order to extract the
     * @return Pinned memory resource owner thing or null on error
     */
    private static PinnedFile pinFile(String fileToPin,
                                      int maxBytesToPin,
                                      boolean attemptPinIntrospection) {
        ZipFile fileAsZip = null;
        InputStream pinRangeStream = null;
        try {
            if (attemptPinIntrospection) {
                fileAsZip = maybeOpenZip(fileToPin);
            }

            if (fileAsZip != null) {
                pinRangeStream = maybeOpenPinMetaInZip(fileAsZip, fileToPin);
            }

            Slog.d(TAG, "pinRangeStream: " + pinRangeStream);

            PinRangeSource pinRangeSource = (pinRangeStream != null)
                ? new PinRangeSourceStream(pinRangeStream)
                : new PinRangeSourceStatic(0, Integer.MAX_VALUE /* will be clipped */);
            return pinFileRanges(fileToPin, maxBytesToPin, pinRangeSource);
        } finally {
            safeClose(pinRangeStream);
            safeClose(fileAsZip);  // Also closes any streams we've opened
        }
    }

    /**
     * Attempt to open a file as a zip file. On any sort of corruption, log, swallow the
     * error, and return null.
     */
    private static ZipFile maybeOpenZip(String fileName) {
        ZipFile zip = null;
        try {
            zip = new ZipFile(fileName);
        } catch (IOException ex) {
            Slog.w(TAG,
                   String.format(
                       "could not open \"%s\" as zip: pinning as blob",
                                 fileName),
                   ex);
        }
        return zip;
    }

    /**
     * Open a pin metadata file in the zip if one is present.
     *
     * @param zipFile Zip file to search
     * @return Open input stream or null on any error
     */
    private static InputStream maybeOpenPinMetaInZip(ZipFile zipFile, String fileName) {
        ZipEntry pinMetaEntry = zipFile.getEntry(PIN_META_FILENAME);
        InputStream pinMetaStream = null;
        if (pinMetaEntry != null) {
            try {
                pinMetaStream = zipFile.getInputStream(pinMetaEntry);
            } catch (IOException ex) {
                Slog.w(TAG,
                       String.format("error reading pin metadata \"%s\": pinning as blob",
                                     fileName),
                       ex);
            }
        }
        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.
     *
     * @param fileToPin Name of file to pin
     * @param maxBytesToPin Maximum number of bytes to pin
     * @param pinRangeSource Read PIN_RANGE entries from this stream to tell us what bytes
     *   to pin.
     * @return PinnedFile or null on error
     */
    private static PinnedFile pinFileRanges(
        String fileToPin,
        int maxBytesToPin,
        PinRangeSource pinRangeSource)
    {
        FileDescriptor fd = new FileDescriptor();
        long address = -1;
        int mapSize = 0;

        try {
            int openFlags = (OsConstants.O_RDONLY |
                             OsConstants.O_CLOEXEC |
                             OsConstants.O_NOFOLLOW);
            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);

            PinRange pinRange = new PinRange();
            int bytesPinned = 0;

            // We pin at page granularity, so make sure the limit is page-aligned
            if (maxBytesToPin % PAGE_SIZE != 0) {
                maxBytesToPin -= maxBytesToPin % PAGE_SIZE;
            }

            while (bytesPinned < maxBytesToPin && pinRangeSource.read(pinRange)) {
                int pinStart = pinRange.start;
                int pinLength = pinRange.length;
                pinStart = clamp(0, pinStart, mapSize);
                pinLength = 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
                // lock region to page boundaries anyway so that we don't under-count
                // locking a single byte of a page as a charge of one byte even though the
                // OS will retain the whole page. Thanks to this adjustment, we slightly
                // over-count the pin charge of back-to-back pins touching the same page,
                // but better that than undercounting. Besides: nothing stops pin metafile
                // creators from making the actual regions page-aligned.
                pinLength += pinStart % PAGE_SIZE;
                pinStart -= pinStart % PAGE_SIZE;
                if (pinLength % PAGE_SIZE != 0) {
                    pinLength += PAGE_SIZE - pinLength % PAGE_SIZE;
                }
                pinLength = 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));
                    }
                    Os.mlock(address + pinStart, pinLength);
                }
                bytesPinned += pinLength;
            }

            PinnedFile pinnedFile = new PinnedFile(address, mapSize, fileToPin, bytesPinned);
            address = -1;  // Ownership transferred
            return pinnedFile;
        } catch (ErrnoException ex) {
            Slog.e(TAG, "Could not pin file " + fileToPin, ex);
            return null;
        } finally {
            safeClose(fd);
            if (address >= 0) {
                safeMunmap(address, mapSize);
            }
        }
    }

    private static int clamp(int min, int value, int 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);
            }
        }
    }

    private final class BinderService extends Binder {
        @Override
        protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
            if (!DumpUtils.checkDumpPermission(mContext, TAG, pw)) return;
            synchronized (PinnerService.this) {
                long totalSize = 0;
                for (PinnedFile pinnedFile : mPinnedFiles) {
                    pw.format("%s %s\n", pinnedFile.fileName, pinnedFile.bytesPinned);
                    totalSize += pinnedFile.bytesPinned;
                }
                pw.println();
                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.println();
                    for (PinnedFile pf : mPinnedApps.get(key).mFiles) {
                        pw.print("  "); pw.format("%s %s\n", pf.fileName, pf.bytesPinned);
                        totalSize += pf.bytesPinned;
                    }
                }
                pw.format("Total size: %s\n", totalSize);
                pw.println();
                if (!mPendingRepin.isEmpty()) {
                    pw.print("Pending repin: ");
                    for (int key : mPendingRepin.values()) {
                        pw.print(getNameForKey(key)); pw.print(' ');
                    }
                    pw.println();
                }
            }
        }
    }

    private static final class PinnedFile implements AutoCloseable {
        private long mAddress;
        final int mapSize;
        final String fileName;
        final int bytesPinned;

        PinnedFile(long address, int mapSize, String fileName, int bytesPinned) {
             mAddress = address;
             this.mapSize = mapSize;
             this.fileName = fileName;
             this.bytesPinned = bytesPinned;
        }

        @Override
        public void close() {
            if (mAddress >= 0) {
                safeMunmap(mAddress, mapSize);
                mAddress = -1;
            }
        }

        @Override
        public void finalize() {
            close();
        }
    }

    final static class PinRange {
        int start;
        int length;
    }

    /**
     * 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.
         */
        final int uid;

        /** Whether it is currently active, i.e. there is a running process from that package. */
        boolean active;

        /** List of pinned files. */
        final ArrayList<PinnedFile> mFiles = new ArrayList<>();

        private PinnedApp(ApplicationInfo appInfo) {
            uid = appInfo.uid;
            active = mAmInternal.isUidActive(uid);
        }
    }

    final class PinnerHandler extends Handler {
        static final int PIN_ONSTART_MSG = 4001;

        public PinnerHandler(Looper looper) {
            super(looper, null, true);
        }

        @Override
        public void handleMessage(Message msg) {
            switch (msg.what) {
                case PIN_ONSTART_MSG:
                {
                    handlePinOnStart();
                }
                break;

                default:
                    super.handleMessage(msg);
            }
        }
    }

}
