/*
 * Copyright (C) 2006 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.am;

import static com.android.server.am.ActivityManagerDebugConfig.TAG_AM;
import static com.android.server.am.ActivityManagerDebugConfig.TAG_WITH_CLASS_NAME;
import static com.android.server.am.ActivityManagerService.MY_PID;

import android.annotation.Nullable;
import android.app.ActivityManager;
import android.app.ApplicationExitInfo;
import android.app.ApplicationExitInfo.Reason;
import android.app.ApplicationExitInfo.SubReason;
import android.app.IApplicationThread;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManagerInternal;
import android.content.pm.ProcessInfo;
import android.content.pm.VersionedPackage;
import android.content.res.CompatibilityInfo;
import android.os.Binder;
import android.os.Bundle;
import android.os.IBinder;
import android.os.Process;
import android.os.RemoteException;
import android.os.SystemClock;
import android.os.Trace;
import android.os.UserHandle;
import android.server.ServerProtoEnums;
import android.util.ArrayMap;
import android.util.ArraySet;
import android.util.DebugUtils;
import android.util.EventLog;
import android.util.Slog;
import android.util.TimeUtils;
import android.util.proto.ProtoOutputStream;

import com.android.internal.annotations.CompositeRWLock;
import com.android.internal.annotations.GuardedBy;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.app.procstats.ProcessState;
import com.android.internal.app.procstats.ProcessStats;
import com.android.internal.os.Zygote;
import com.android.internal.util.FrameworkStatsLog;
import com.android.server.wm.WindowProcessController;
import com.android.server.wm.WindowProcessListener;

import java.io.PrintWriter;
import java.util.Arrays;
import java.util.List;
import java.util.Objects;

/**
 * Full information about a particular process that
 * is currently running.
 */
class ProcessRecord implements WindowProcessListener {
    static final String TAG = TAG_WITH_CLASS_NAME ? "ProcessRecord" : TAG_AM;

    final ActivityManagerService mService; // where we came from
    private final ActivityManagerGlobalLock mProcLock;

    // =========================================================
    // Basic info of the process, immutable or semi-immutable over
    // the lifecycle of the process
    // =========================================================
    volatile ApplicationInfo info; // all about the first app in the process
    final ProcessInfo processInfo; // if non-null, process-specific manifest info
    final boolean isolated;     // true if this is a special isolated process
    public final boolean isSdkSandbox; // true if this is an SDK sandbox process
    final boolean appZygote;    // true if this is forked from the app zygote
    final int uid;              // uid of process; may be different from 'info' if isolated
    final int userId;           // user of process.
    final String processName;   // name of the process
    final String sdkSandboxClientAppPackage; // if this is an sdk sandbox process, name of the
                                             // app package for which it is running
    final String sdkSandboxClientAppVolumeUuid; // uuid of the app for which the sandbox is running

    /**
     * Overall state of process's uid.
     */
    @CompositeRWLock({"mService", "mProcLock"})
    private UidRecord mUidRecord;

    /**
     * List of packages running in the process.
     */
    private final PackageList mPkgList = new PackageList(this);

    /**
     * Additional packages we have a dependency on.
     */
    @CompositeRWLock({"mService", "mProcLock"})
    private ArraySet<String> mPkgDeps;

    /**
     * The process of this application; 0 if none.
     */
    @CompositeRWLock({"mService", "mProcLock"})
    int mPid;

    /**
     * The process ID which will be set when we're killing this process.
     */
    @GuardedBy("mService")
    private int mDyingPid;

    /**
     * The gids this process was launched with.
     */
    @GuardedBy("mService")
    private int[] mGids;

    /**
     * The ABI this process was launched with.
     */
    @GuardedBy("mService")
    private String mRequiredAbi;

    /**
     * The instruction set this process was launched with.
     */
    @GuardedBy("mService")
    private String mInstructionSet;

    /**
     * The actual proc...  may be null only if 'persistent' is true
     * (in which case we are in the process of launching the app).
     */
    @CompositeRWLock({"mService", "mProcLock"})
    private IApplicationThread mThread;

    /**
     * Always keep this application running?
     */
    private volatile boolean mPersistent;

    /**
     * Caching of toShortString() result.
     * <p>Note: No lock here, it doesn't matter in case of race condition</p>
     */
    private String mShortStringName;

    /**
     * Caching of toString() result.
     * <p>Note: No lock here, it doesn't matter in case of race condition</p>
     */
    private String mStringName;

    /**
     * Process start is pending.
     */
    @GuardedBy("mService")
    private boolean mPendingStart;

    /**
     * Seq no. Indicating the latest process start associated with this process record.
     */
    @GuardedBy("mService")
    private long mStartSeq;

    /**
     * Params used in starting this process.
     */
    private volatile HostingRecord mHostingRecord;

    /**
     * Selinux info of this process.
     */
    private volatile String mSeInfo;

    /**
     * When the process is started. (before zygote fork)
     */
    private volatile long mStartUptime;

    /**
     * When the process is started. (before zygote fork)
     */
    private volatile long mStartElapsedTime;

    /**
     * This will be same as {@link #uid} usually except for some apps used during factory testing.
     */
    private volatile int mStartUid;

    /**
     * Indicates how the external storage was mounted for this process.
     */
    private volatile int mMountMode;

    /**
     * True if Android/obb and Android/data need to be bind mount.
     */
    private volatile boolean mBindMountPending;

    /**
     * True when proc was started in user unlocked state.
     */
    @GuardedBy("mProcLock")
    private boolean mUnlocked;

    /**
     * TID for RenderThread.
     */
    @GuardedBy("mProcLock")
    private int mRenderThreadTid;

    /**
     * Last used compatibility mode.
     */
    @GuardedBy("mService")
    private CompatibilityInfo mCompat;

    /**
     * Set of disabled compat changes for the process (all others are enabled).
     */
    @GuardedBy("mService")
    private long[] mDisabledCompatChanges;

    /**
     * Who is watching for the death.
     */
    @GuardedBy("mService")
    private IBinder.DeathRecipient mDeathRecipient;

    /**
     * Set to currently active instrumentation running in process.
     */
    @CompositeRWLock({"mService", "mProcLock"})
    private ActiveInstrumentation mInstr;

    /**
     * True when proc has been killed by activity manager, not for RAM.
     */
    @CompositeRWLock({"mService", "mProcLock"})
    private boolean mKilledByAm;

    /**
     * True once we know the process has been killed.
     */
    @CompositeRWLock({"mService", "mProcLock"})
    private boolean mKilled;

    /**
     * The timestamp in uptime when this process was killed.
     */
    @CompositeRWLock({"mService", "mProcLock"})
    private long mKillTime;

    /**
     * Process is waiting to be killed when in the bg, and reason.
     */
    @GuardedBy("mService")
    private String mWaitingToKill;

    /**
     * Whether this process should be killed and removed from process list.
     * It is set when the package is force-stopped or the process has crashed too many times.
     */
    private volatile boolean mRemoved;

    /**
     * Was app launched for debugging?
     */
    @GuardedBy("mService")
    private boolean mDebugging;

    /**
     * Has process show wait for debugger dialog?
     */
    @GuardedBy("mProcLock")
    private boolean mWaitedForDebugger;

    /**
     * For managing the LRU list.
     */
    @CompositeRWLock({"mService", "mProcLock"})
    private long mLastActivityTime;

    /**
     * Set to true when process was launched with a wrapper attached.
     */
    @GuardedBy("mService")
    private boolean mUsingWrapper;

    /**
     * Sequence id for identifying LRU update cycles.
     */
    @GuardedBy("mService")
    private int mLruSeq;

    /**
     * Class to run on start if this is a special isolated process.
     */
    @GuardedBy("mService")
    private String mIsolatedEntryPoint;

    /**
     * Arguments to pass to isolatedEntryPoint's main().
     */
    @GuardedBy("mService")
    private String[] mIsolatedEntryPointArgs;

    /**
     * Process is currently hosting a backup agent for backup or restore.
     */
    @GuardedBy("mService")
    private boolean mInFullBackup;

    /**
     * Controller for driving the process state on the window manager side.
     */
    private final WindowProcessController mWindowProcessController;

    /**
     * Profiling info of the process, such as PSS, cpu, etc.
     */
    final ProcessProfileRecord mProfile;

    /**
     * All about the services in this process.
     */
    final ProcessServiceRecord mServices;

    /**
     * All about the providers in this process.
     */
    final ProcessProviderRecord mProviders;

    /**
     * All about the receivers in this process.
     */
    final ProcessReceiverRecord mReceivers;

    /**
     * All about the error state(crash, ANR) in this process.
     */
    final ProcessErrorStateRecord mErrorState;

    /**
     * All about the process state info (proc state, oom adj score) in this process.
     */
    final ProcessStateRecord mState;

    /**
     * All about the state info of the optimizer when the process is cached.
     */
    final ProcessCachedOptimizerRecord mOptRecord;

    /**
     * The preceding instance of the process, which would exist when the previous process is killed
     * but not fully dead yet; in this case, the new instance of the process should be held until
     * this preceding instance is fully dead.
     */
    volatile ProcessRecord mPredecessor;

    /**
     * The succeeding instance of the process, which is going to be started after this process
     * is killed successfully.
     */
    volatile ProcessRecord mSuccessor;

    /**
     * The routine to start its successor process.
     *
     * <p>Note: It should be accessed from process start thread only.</p>
     */
    Runnable mSuccessorStartRunnable;

    void setStartParams(int startUid, HostingRecord hostingRecord, String seInfo,
            long startUptime, long startElapsedTime) {
        this.mStartUid = startUid;
        this.mHostingRecord = hostingRecord;
        this.mSeInfo = seInfo;
        this.mStartUptime = startUptime;
        this.mStartElapsedTime = startElapsedTime;
    }

    @GuardedBy({"mService", "mProcLock"})
    void dump(PrintWriter pw, String prefix) {
        final long nowUptime = SystemClock.uptimeMillis();
        final long nowElapsedTime = SystemClock.elapsedRealtime();

        pw.print(prefix); pw.print("user #"); pw.print(userId);
                pw.print(" uid="); pw.print(info.uid);
        if (uid != info.uid) {
            pw.print(" ISOLATED uid="); pw.print(uid);
        }
        pw.print(" gids={");
        if (mGids != null) {
            for (int gi = 0; gi < mGids.length; gi++) {
                if (gi != 0) pw.print(", ");
                pw.print(mGids[gi]);

            }
        }
        pw.println("}");
        if (processInfo != null) {
            pw.print(prefix); pw.println("processInfo:");
            if (processInfo.deniedPermissions != null) {
                for (int i = 0; i < processInfo.deniedPermissions.size(); i++) {
                    pw.print(prefix); pw.print("  deny: ");
                    pw.println(processInfo.deniedPermissions.valueAt(i));
                }
            }
            if (processInfo.gwpAsanMode != ApplicationInfo.GWP_ASAN_DEFAULT) {
                pw.print(prefix); pw.println("  gwpAsanMode=" + processInfo.gwpAsanMode);
            }
            if (processInfo.memtagMode != ApplicationInfo.MEMTAG_DEFAULT) {
                pw.print(prefix); pw.println("  memtagMode=" + processInfo.memtagMode);
            }
        }
        pw.print(prefix); pw.print("mRequiredAbi="); pw.print(mRequiredAbi);
        pw.print(" instructionSet="); pw.println(mInstructionSet);
        if (info.className != null) {
            pw.print(prefix); pw.print("class="); pw.println(info.className);
        }
        if (info.manageSpaceActivityName != null) {
            pw.print(prefix); pw.print("manageSpaceActivityName=");
            pw.println(info.manageSpaceActivityName);
        }

        pw.print(prefix); pw.print("dir="); pw.print(info.sourceDir);
                pw.print(" publicDir="); pw.print(info.publicSourceDir);
                pw.print(" data="); pw.println(info.dataDir);
        mPkgList.dump(pw, prefix);
        if (mPkgDeps != null) {
            pw.print(prefix); pw.print("packageDependencies={");
            for (int i = 0; i < mPkgDeps.size(); i++) {
                if (i > 0) pw.print(", ");
                pw.print(mPkgDeps.valueAt(i));
            }
            pw.println("}");
        }
        pw.print(prefix); pw.print("compat="); pw.println(mCompat);
        if (mInstr != null) {
            pw.print(prefix); pw.print("mInstr="); pw.println(mInstr);
        }
        pw.print(prefix); pw.print("thread="); pw.println(mThread);
        pw.print(prefix); pw.print("pid="); pw.println(mPid);
        pw.print(prefix); pw.print("lastActivityTime=");
        TimeUtils.formatDuration(mLastActivityTime, nowUptime, pw);
        pw.print(prefix); pw.print("startUptimeTime=");
        TimeUtils.formatDuration(mStartElapsedTime, nowUptime, pw);
        pw.print(prefix); pw.print("startElapsedTime=");
        TimeUtils.formatDuration(mStartElapsedTime, nowElapsedTime, pw);
        pw.println();
        if (mPersistent || mRemoved) {
            pw.print(prefix); pw.print("persistent="); pw.print(mPersistent);
            pw.print(" removed="); pw.println(mRemoved);
        }
        if (mDebugging) {
            pw.print(prefix); pw.print("mDebugging="); pw.println(mDebugging);
        }
        if (mPendingStart) {
            pw.print(prefix); pw.print("pendingStart="); pw.println(mPendingStart);
        }
        pw.print(prefix); pw.print("startSeq="); pw.println(mStartSeq);
        pw.print(prefix); pw.print("mountMode="); pw.println(
                DebugUtils.valueToString(Zygote.class, "MOUNT_EXTERNAL_", mMountMode));
        if (mKilled || mKilledByAm || mWaitingToKill != null) {
            pw.print(prefix); pw.print("killed="); pw.print(mKilled);
            pw.print(" killedByAm="); pw.print(mKilledByAm);
            pw.print(" waitingToKill="); pw.println(mWaitingToKill);
        }
        if (mIsolatedEntryPoint != null || mIsolatedEntryPointArgs != null) {
            pw.print(prefix); pw.print("isolatedEntryPoint="); pw.println(mIsolatedEntryPoint);
            pw.print(prefix); pw.print("isolatedEntryPointArgs=");
            pw.println(Arrays.toString(mIsolatedEntryPointArgs));
        }
        if (mState.getSetProcState() > ActivityManager.PROCESS_STATE_SERVICE) {
            mProfile.dumpCputime(pw, prefix);
        }
        mProfile.dumpPss(pw, prefix, nowUptime);
        mState.dump(pw, prefix, nowUptime);
        mErrorState.dump(pw, prefix, nowUptime);
        mServices.dump(pw, prefix, nowUptime);
        mProviders.dump(pw, prefix, nowUptime);
        mReceivers.dump(pw, prefix, nowUptime);
        mOptRecord.dump(pw, prefix, nowUptime);
        mWindowProcessController.dump(pw, prefix);
    }

    ProcessRecord(ActivityManagerService _service, ApplicationInfo _info, String _processName,
            int _uid) {
        this(_service, _info, _processName, _uid, null, -1, null);
    }

    ProcessRecord(ActivityManagerService _service, ApplicationInfo _info, String _processName,
            int _uid, String _sdkSandboxClientAppPackage, int _definingUid,
            String _definingProcessName) {
        mService = _service;
        mProcLock = _service.mProcLock;
        info = _info;
        ProcessInfo procInfo = null;
        if (_service.mPackageManagerInt != null) {
            if (_definingUid > 0) {
                ArrayMap<String, ProcessInfo> processes =
                        _service.mPackageManagerInt.getProcessesForUid(_definingUid);
                if (processes != null) procInfo = processes.get(_definingProcessName);
            } else {
                ArrayMap<String, ProcessInfo> processes =
                        _service.mPackageManagerInt.getProcessesForUid(_uid);
                if (processes != null) procInfo = processes.get(_processName);
            }
            if (procInfo != null && procInfo.deniedPermissions == null
                    && procInfo.gwpAsanMode == ApplicationInfo.GWP_ASAN_DEFAULT
                    && procInfo.memtagMode == ApplicationInfo.MEMTAG_DEFAULT
                    && procInfo.nativeHeapZeroInitialized == ApplicationInfo.ZEROINIT_DEFAULT) {
                // If this process hasn't asked for permissions to be denied, or for a
                // non-default GwpAsan mode, or any other non-default setting, then we don't
                // care about it.
                procInfo = null;
            }
        }
        processInfo = procInfo;
        isolated = Process.isIsolated(_uid);
        isSdkSandbox = Process.isSdkSandboxUid(_uid);
        appZygote = (UserHandle.getAppId(_uid) >= Process.FIRST_APP_ZYGOTE_ISOLATED_UID
                && UserHandle.getAppId(_uid) <= Process.LAST_APP_ZYGOTE_ISOLATED_UID);
        uid = _uid;
        userId = UserHandle.getUserId(_uid);
        processName = _processName;
        sdkSandboxClientAppPackage = _sdkSandboxClientAppPackage;
        if (isSdkSandbox) {
            sdkSandboxClientAppVolumeUuid = getClientInfoForSdkSandbox().volumeUuid;
        } else {
            sdkSandboxClientAppVolumeUuid = null;
        }
        mPersistent = false;
        mRemoved = false;
        mProfile = new ProcessProfileRecord(this);
        mServices = new ProcessServiceRecord(this);
        mProviders = new ProcessProviderRecord(this);
        mReceivers = new ProcessReceiverRecord(this);
        mErrorState = new ProcessErrorStateRecord(this);
        mState = new ProcessStateRecord(this);
        mOptRecord = new ProcessCachedOptimizerRecord(this);
        final long now = SystemClock.uptimeMillis();
        mProfile.init(now);
        mOptRecord.init(now);
        mState.init(now);
        mWindowProcessController = new WindowProcessController(
                mService.mActivityTaskManager, info, processName, uid, userId, this, this);
        mPkgList.put(_info.packageName, new ProcessStats.ProcessStateHolder(_info.longVersionCode));
    }

    @GuardedBy(anyOf = {"mService", "mProcLock"})
    UidRecord getUidRecord() {
        return mUidRecord;
    }

    @GuardedBy({"mService", "mProcLock"})
    void setUidRecord(UidRecord uidRecord) {
        mUidRecord = uidRecord;
    }

    PackageList getPkgList() {
        return mPkgList;
    }

    @GuardedBy(anyOf = {"mService", "mProcLock"})
    ArraySet<String> getPkgDeps() {
        return mPkgDeps;
    }

    @GuardedBy({"mService", "mProcLock"})
    void setPkgDeps(ArraySet<String> pkgDeps) {
        mPkgDeps = pkgDeps;
    }

    @GuardedBy(anyOf = {"mService", "mProcLock"})
    int getPid() {
        return mPid;
    }

    @GuardedBy({"mService", "mProcLock"})
    void setPid(int pid) {
        mPid = pid;
        mWindowProcessController.setPid(pid);
        mShortStringName = null;
        mStringName = null;
        synchronized (mProfile.mProfilerLock) {
            mProfile.setPid(pid);
        }
    }

    @GuardedBy(anyOf = {"mService", "mProcLock"})
    IApplicationThread getThread() {
        return mThread;
    }

    @GuardedBy({"mService", "mProcLock"})
    public void makeActive(IApplicationThread thread, ProcessStatsService tracker) {
        mProfile.onProcessActive(thread, tracker);
        mThread = thread;
        mWindowProcessController.setThread(thread);
    }

    @GuardedBy({"mService", "mProcLock"})
    public void makeInactive(ProcessStatsService tracker) {
        mThread = null;
        mWindowProcessController.setThread(null);
        mProfile.onProcessInactive(tracker);
    }

    @GuardedBy("mService")
    int getDyingPid() {
        return mDyingPid;
    }

    @GuardedBy("mService")
    void setDyingPid(int dyingPid) {
        mDyingPid = dyingPid;
    }

    @GuardedBy("mService")
    int[] getGids() {
        return mGids;
    }

    @GuardedBy("mService")
    void setGids(int[] gids) {
        mGids = gids;
    }

    @GuardedBy("mService")
    String getRequiredAbi() {
        return mRequiredAbi;
    }

    @GuardedBy("mService")
    void setRequiredAbi(String requiredAbi) {
        mRequiredAbi = requiredAbi;
        mWindowProcessController.setRequiredAbi(requiredAbi);
    }

    @GuardedBy("mService")
    String getInstructionSet() {
        return mInstructionSet;
    }

    @GuardedBy("mService")
    void setInstructionSet(String instructionSet) {
        mInstructionSet = instructionSet;
    }

    void setPersistent(boolean persistent) {
        mPersistent = persistent;
        mWindowProcessController.setPersistent(persistent);
    }

    boolean isPersistent() {
        return mPersistent;
    }

    @GuardedBy("mService")
    boolean isPendingStart() {
        return mPendingStart;
    }

    @GuardedBy("mService")
    void setPendingStart(boolean pendingStart) {
        mPendingStart = pendingStart;
    }

    @GuardedBy("mService")
    long getStartSeq() {
        return mStartSeq;
    }

    @GuardedBy("mService")
    void setStartSeq(long startSeq) {
        mStartSeq = startSeq;
    }

    HostingRecord getHostingRecord() {
        return mHostingRecord;
    }

    void setHostingRecord(HostingRecord hostingRecord) {
        mHostingRecord = hostingRecord;
    }

    String getSeInfo() {
        return mSeInfo;
    }

    void setSeInfo(String seInfo) {
        mSeInfo = seInfo;
    }

    long getStartUptime() {
        return mStartUptime;
    }

    /**
     * Same as {@link #getStartUptime()}.
     * @deprecated use {@link #getStartUptime()} instead for clarity.
     */
    @Deprecated
    long getStartTime() {
        return mStartUptime;
    }

    long getStartElapsedTime() {
        return mStartElapsedTime;
    }

    int getStartUid() {
        return mStartUid;
    }

    void setStartUid(int startUid) {
        mStartUid = startUid;
    }

    int getMountMode() {
        return mMountMode;
    }

    void setMountMode(int mountMode) {
        mMountMode = mountMode;
    }

    boolean isBindMountPending() {
        return mBindMountPending;
    }

    void setBindMountPending(boolean bindMountPending) {
        mBindMountPending = bindMountPending;
    }

    @GuardedBy("mProcLock")
    boolean isUnlocked() {
        return mUnlocked;
    }

    @GuardedBy("mProcLock")
    void setUnlocked(boolean unlocked) {
        mUnlocked = unlocked;
    }

    @GuardedBy("mProcLock")
    int getRenderThreadTid() {
        return mRenderThreadTid;
    }

    @GuardedBy("mProcLock")
    void setRenderThreadTid(int renderThreadTid) {
        mRenderThreadTid = renderThreadTid;
    }

    @GuardedBy("mService")
    CompatibilityInfo getCompat() {
        return mCompat;
    }

    @GuardedBy("mService")
    void setCompat(CompatibilityInfo compat) {
        mCompat = compat;
    }

    @GuardedBy("mService")
    long[] getDisabledCompatChanges() {
        return mDisabledCompatChanges;
    }

    @GuardedBy("mService")
    void setDisabledCompatChanges(long[] disabledCompatChanges) {
        mDisabledCompatChanges = disabledCompatChanges;
    }

    @GuardedBy("mService")
    void unlinkDeathRecipient() {
        if (mDeathRecipient != null && mThread != null) {
            mThread.asBinder().unlinkToDeath(mDeathRecipient, 0);
        }
        mDeathRecipient = null;
    }

    @GuardedBy("mService")
    void setDeathRecipient(IBinder.DeathRecipient deathRecipient) {
        mDeathRecipient = deathRecipient;
    }

    @GuardedBy("mService")
    IBinder.DeathRecipient getDeathRecipient() {
        return mDeathRecipient;
    }

    @GuardedBy({"mService", "mProcLock"})
    void setActiveInstrumentation(ActiveInstrumentation instr) {
        mInstr = instr;
        boolean isInstrumenting = instr != null;
        mWindowProcessController.setInstrumenting(
                isInstrumenting,
                isInstrumenting ? instr.mSourceUid : -1,
                isInstrumenting && instr.mHasBackgroundActivityStartsPermission);
    }

    @GuardedBy(anyOf = {"mService", "mProcLock"})
    ActiveInstrumentation getActiveInstrumentation() {
        return mInstr;
    }

    @GuardedBy(anyOf = {"mService", "mProcLock"})
    boolean isKilledByAm() {
        return mKilledByAm;
    }

    @GuardedBy({"mService", "mProcLock"})
    void setKilledByAm(boolean killedByAm) {
        mKilledByAm = killedByAm;
    }

    @GuardedBy(anyOf = {"mService", "mProcLock"})
    boolean isKilled() {
        return mKilled;
    }

    @GuardedBy({"mService", "mProcLock"})
    void setKilled(boolean killed) {
        mKilled = killed;
    }

    @GuardedBy(anyOf = {"mService", "mProcLock"})
    long getKillTime() {
        return mKillTime;
    }

    @GuardedBy({"mService", "mProcLock"})
    void setKillTime(long killTime) {
        mKillTime = killTime;
    }

    @GuardedBy("mService")
    String getWaitingToKill() {
        return mWaitingToKill;
    }

    @GuardedBy("mService")
    void setWaitingToKill(String waitingToKill) {
        mWaitingToKill = waitingToKill;
    }

    @Override
    public boolean isRemoved() {
        return mRemoved;
    }

    void setRemoved(boolean removed) {
        mRemoved = removed;
    }

    @GuardedBy("mService")
    boolean isDebugging() {
        return mDebugging;
    }

    @Nullable
    public ApplicationInfo getClientInfoForSdkSandbox() {
        if (!isSdkSandbox || sdkSandboxClientAppPackage == null) {
            throw new IllegalStateException(
                    "getClientInfoForSdkSandbox called for non-sandbox process"
            );
        }
        PackageManagerInternal pm = mService.getPackageManagerInternal();
        return pm.getApplicationInfo(
                sdkSandboxClientAppPackage, /* flags */0, Process.SYSTEM_UID, userId);
    }

    public boolean isDebuggable() {
        if ((info.flags & ApplicationInfo.FLAG_DEBUGGABLE) != 0) {
            return true;
        }
        if (isSdkSandbox) {
            ApplicationInfo clientInfo = getClientInfoForSdkSandbox();
            return clientInfo != null && (clientInfo.flags & ApplicationInfo.FLAG_DEBUGGABLE) != 0;
        }
        return false;
    }

    @GuardedBy("mService")
    void setDebugging(boolean debugging) {
        mDebugging = debugging;
        mWindowProcessController.setDebugging(debugging);
    }

    @GuardedBy("mProcLock")
    boolean hasWaitedForDebugger() {
        return mWaitedForDebugger;
    }

    @GuardedBy("mProcLock")
    void setWaitedForDebugger(boolean waitedForDebugger) {
        mWaitedForDebugger = waitedForDebugger;
    }

    @GuardedBy(anyOf = {"mService", "mProcLock"})
    long getLastActivityTime() {
        return mLastActivityTime;
    }

    @GuardedBy({"mService", "mProcLock"})
    void setLastActivityTime(long lastActivityTime) {
        mLastActivityTime = lastActivityTime;
    }

    @GuardedBy("mService")
    boolean isUsingWrapper() {
        return mUsingWrapper;
    }

    @GuardedBy("mService")
    void setUsingWrapper(boolean usingWrapper) {
        mUsingWrapper = usingWrapper;
        mWindowProcessController.setUsingWrapper(usingWrapper);
    }

    @GuardedBy("mService")
    int getLruSeq() {
        return mLruSeq;
    }

    @GuardedBy("mService")
    void setLruSeq(int lruSeq) {
        mLruSeq = lruSeq;
    }

    @GuardedBy("mService")
    String getIsolatedEntryPoint() {
        return mIsolatedEntryPoint;
    }

    @GuardedBy("mService")
    void setIsolatedEntryPoint(String isolatedEntryPoint) {
        mIsolatedEntryPoint = isolatedEntryPoint;
    }

    @GuardedBy("mService")
    String[] getIsolatedEntryPointArgs() {
        return mIsolatedEntryPointArgs;
    }

    @GuardedBy("mService")
    void setIsolatedEntryPointArgs(String[] isolatedEntryPointArgs) {
        mIsolatedEntryPointArgs = isolatedEntryPointArgs;
    }

    @GuardedBy("mService")
    boolean isInFullBackup() {
        return mInFullBackup;
    }

    @GuardedBy("mService")
    void setInFullBackup(boolean inFullBackup) {
        mInFullBackup = inFullBackup;
    }

    @Override
    public boolean isCached() {
        return mState.isCached();
    }

    boolean hasActivities() {
        return mWindowProcessController.hasActivities();
    }

    boolean hasActivitiesOrRecentTasks() {
        return mWindowProcessController.hasActivitiesOrRecentTasks();
    }

    boolean hasRecentTasks() {
        return mWindowProcessController.hasRecentTasks();
    }

    @GuardedBy({"mService", "mProcLock"})
    boolean onCleanupApplicationRecordLSP(ProcessStatsService processStats, boolean allowRestart,
            boolean unlinkDeath) {
        mErrorState.onCleanupApplicationRecordLSP();

        resetPackageList(processStats);
        if (unlinkDeath) {
            unlinkDeathRecipient();
        }
        makeInactive(processStats);
        setWaitingToKill(null);

        mState.onCleanupApplicationRecordLSP();
        mServices.onCleanupApplicationRecordLocked();
        mReceivers.onCleanupApplicationRecordLocked();

        return mProviders.onCleanupApplicationRecordLocked(allowRestart);
    }

    /**
     * This method returns true if any of the activities within the process record are interesting
     * to the user. See HistoryRecord.isInterestingToUserLocked()
     */
    public boolean isInterestingToUserLocked() {
        if (mWindowProcessController.isInterestingToUser()) {
            return true;
        }

        return mServices.hasForegroundServices();
    }

    /**
     * Let an app process throw an exception on a binder thread, which typically crashes the
     * process, unless it has an unhandled exception handler.
     *
     * See {@link ActivityThread#throwRemoteServiceException}.
     *
     * @param message exception message
     * @param exceptionTypeId ID defined in {@link android.app.RemoteServiceException} or one
     *                        of its subclasses.
     */
    @GuardedBy("mService")
    void scheduleCrashLocked(String message, int exceptionTypeId, @Nullable Bundle extras) {
        // Checking killedbyAm should keep it from showing the crash dialog if the process
        // was already dead for a good / normal reason.
        if (!mKilledByAm) {
            if (mThread != null) {
                if (mPid == Process.myPid()) {
                    Slog.w(TAG, "scheduleCrash: trying to crash system process!");
                    return;
                }
                final long ident = Binder.clearCallingIdentity();
                try {
                    mThread.scheduleCrash(message, exceptionTypeId, extras);
                } catch (RemoteException e) {
                    // If it's already dead our work is done. If it's wedged just kill it.
                    // We won't get the crash dialog or the error reporting.
                    killLocked("scheduleCrash for '" + message + "' failed",
                            ApplicationExitInfo.REASON_CRASH, true);
                } finally {
                    Binder.restoreCallingIdentity(ident);
                }
            }
        }
    }

    @GuardedBy("mService")
    void killLocked(String reason, @Reason int reasonCode, boolean noisy) {
        killLocked(reason, reasonCode, ApplicationExitInfo.SUBREASON_UNKNOWN, noisy);
    }

    @GuardedBy("mService")
    void killLocked(String reason, @Reason int reasonCode, @SubReason int subReason,
            boolean noisy) {
        killLocked(reason, reason, reasonCode, subReason, noisy);
    }

    @GuardedBy("mService")
    void killLocked(String reason, String description, @Reason int reasonCode,
            @SubReason int subReason, boolean noisy) {
        if (!mKilledByAm) {
            Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "kill");
            if (reasonCode == ApplicationExitInfo.REASON_ANR
                    && mErrorState.getAnrAnnotation() != null) {
                description = description + ": " + mErrorState.getAnrAnnotation();
            }
            if (mService != null && (noisy || info.uid == mService.mCurOomAdjUid)) {
                mService.reportUidInfoMessageLocked(TAG,
                        "Killing " + toShortString() + " (adj " + mState.getSetAdj()
                        + "): " + reason, info.uid);
            }
            if (mPid > 0) {
                mService.mProcessList.noteAppKill(this, reasonCode, subReason, description);
                EventLog.writeEvent(EventLogTags.AM_KILL,
                        userId, mPid, processName, mState.getSetAdj(), reason);
                Process.killProcessQuiet(mPid);
                ProcessList.killProcessGroup(uid, mPid);
            } else {
                mPendingStart = false;
            }
            if (!mPersistent) {
                synchronized (mProcLock) {
                    mKilled = true;
                    mKilledByAm = true;
                    mKillTime = SystemClock.uptimeMillis();
                }
            }
            Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
        }
    }

    @Override
    public void dumpDebug(ProtoOutputStream proto, long fieldId) {
        dumpDebug(proto, fieldId, -1);
    }

    public void dumpDebug(ProtoOutputStream proto, long fieldId, int lruIndex) {
        long token = proto.start(fieldId);
        proto.write(ProcessRecordProto.PID, mPid);
        proto.write(ProcessRecordProto.PROCESS_NAME, processName);
        proto.write(ProcessRecordProto.UID, info.uid);
        if (UserHandle.getAppId(info.uid) >= Process.FIRST_APPLICATION_UID) {
            proto.write(ProcessRecordProto.USER_ID, userId);
            proto.write(ProcessRecordProto.APP_ID, UserHandle.getAppId(info.uid));
        }
        if (uid != info.uid) {
            proto.write(ProcessRecordProto.ISOLATED_APP_ID, UserHandle.getAppId(uid));
        }
        proto.write(ProcessRecordProto.PERSISTENT, mPersistent);
        if (lruIndex >= 0) {
            proto.write(ProcessRecordProto.LRU_INDEX, lruIndex);
        }
        proto.end(token);
    }

    public String toShortString() {
        final String shortStringName = mShortStringName;
        if (shortStringName != null) {
            return shortStringName;
        }
        StringBuilder sb = new StringBuilder(128);
        toShortString(sb);
        return mShortStringName = sb.toString();
    }

    void toShortString(StringBuilder sb) {
        sb.append(mPid);
        sb.append(':');
        sb.append(processName);
        sb.append('/');
        if (info.uid < Process.FIRST_APPLICATION_UID) {
            sb.append(uid);
        } else {
            sb.append('u');
            sb.append(userId);
            int appId = UserHandle.getAppId(info.uid);
            if (appId >= Process.FIRST_APPLICATION_UID) {
                sb.append('a');
                sb.append(appId - Process.FIRST_APPLICATION_UID);
            } else {
                sb.append('s');
                sb.append(appId);
            }
            if (uid != info.uid) {
                sb.append('i');
                sb.append(UserHandle.getAppId(uid) - Process.FIRST_ISOLATED_UID);
            }
        }
    }

    public String toString() {
        final String stringName = mStringName;
        if (stringName != null) {
            return stringName;
        }
        StringBuilder sb = new StringBuilder(128);
        sb.append("ProcessRecord{");
        sb.append(Integer.toHexString(System.identityHashCode(this)));
        sb.append(' ');
        toShortString(sb);
        sb.append('}');
        return mStringName = sb.toString();
    }

    /*
     *  Return true if package has been added false if not
     */
    public boolean addPackage(String pkg, long versionCode, ProcessStatsService tracker) {
        synchronized (tracker.mLock) {
            synchronized (mPkgList) {
                if (!mPkgList.containsKey(pkg)) {
                    ProcessStats.ProcessStateHolder holder = new ProcessStats.ProcessStateHolder(
                            versionCode);
                    final ProcessState baseProcessTracker = mProfile.getBaseProcessTracker();
                    if (baseProcessTracker != null) {
                        tracker.updateProcessStateHolderLocked(holder, pkg, info.uid, versionCode,
                                processName);
                        mPkgList.put(pkg, holder);
                        if (holder.state != baseProcessTracker) {
                            holder.state.makeActive();
                        }
                    } else {
                        mPkgList.put(pkg, holder);
                    }
                    return true;
                }
            }
        }
        return false;
    }

    /*
     *  Delete all packages from list except the package indicated in info
     */
    public void resetPackageList(ProcessStatsService tracker) {
        synchronized (tracker.mLock) {
            final ProcessState baseProcessTracker = mProfile.getBaseProcessTracker();
            synchronized (mPkgList) {
                final int numOfPkgs = mPkgList.size();
                if (baseProcessTracker != null) {
                    long now = SystemClock.uptimeMillis();
                    baseProcessTracker.setState(ProcessStats.STATE_NOTHING,
                            tracker.getMemFactorLocked(), now, mPkgList.getPackageListLocked());
                    mPkgList.forEachPackage((pkgName, holder) ->
                            FrameworkStatsLog.write(FrameworkStatsLog.PROCESS_STATE_CHANGED,
                                uid, processName, pkgName,
                                ActivityManager.processStateAmToProto(ProcessStats.STATE_NOTHING),
                                holder.appVersion)
                    );
                    if (numOfPkgs != 1) {
                        mPkgList.forEachPackageProcessStats(holder -> {
                            if (holder.state != null && holder.state != baseProcessTracker) {
                                holder.state.makeInactive();
                            }
                        });
                        mPkgList.clear();
                        ProcessStats.ProcessStateHolder holder =
                                new ProcessStats.ProcessStateHolder(info.longVersionCode);
                        tracker.updateProcessStateHolderLocked(holder, info.packageName, info.uid,
                                info.longVersionCode, processName);
                        mPkgList.put(info.packageName, holder);
                        if (holder.state != baseProcessTracker) {
                            holder.state.makeActive();
                        }
                    }
                } else if (numOfPkgs != 1) {
                    mPkgList.clear();
                    mPkgList.put(info.packageName,
                            new ProcessStats.ProcessStateHolder(info.longVersionCode));
                }
            }
        }
    }

    String[] getPackageList() {
        return mPkgList.getPackageList();
    }

    List<VersionedPackage> getPackageListWithVersionCode() {
        return mPkgList.getPackageListWithVersionCode();
    }

    WindowProcessController getWindowProcessController() {
        return mWindowProcessController;
    }

    /**
     * Allows background activity starts using token {@param entity}. Optionally, you can provide
     * {@param originatingToken} if you have one such originating token, this is useful for tracing
     * back the grant in the case of the notification token.
     */
    void addOrUpdateAllowBackgroundActivityStartsToken(Binder entity,
            @Nullable IBinder originatingToken) {
        Objects.requireNonNull(entity);
        mWindowProcessController.addOrUpdateAllowBackgroundActivityStartsToken(entity,
                originatingToken);
    }

    void removeAllowBackgroundActivityStartsToken(Binder entity) {
        Objects.requireNonNull(entity);
        mWindowProcessController.removeAllowBackgroundActivityStartsToken(entity);
    }

    @Override
    public void clearProfilerIfNeeded() {
        synchronized (mService.mAppProfiler.mProfilerLock) {
            mService.mAppProfiler.clearProfilerLPf();
        }
    }

    @Override
    public void updateServiceConnectionActivities() {
        synchronized (mService) {
            mService.mServices.updateServiceConnectionActivitiesLocked(mServices);
        }
    }

    @Override
    public void setPendingUiClean(boolean pendingUiClean) {
        synchronized (mProcLock) {
            mProfile.setPendingUiClean(pendingUiClean);
        }
    }

    @Override
    public void setPendingUiCleanAndForceProcessStateUpTo(int newState) {
        synchronized (mService) {
            setPendingUiClean(true);
            mState.forceProcessStateUpTo(newState);
        }
    }

    @Override
    public void updateProcessInfo(boolean updateServiceConnectionActivities, boolean activityChange,
            boolean updateOomAdj) {
        synchronized (mService) {
            if (updateServiceConnectionActivities) {
                mService.mServices.updateServiceConnectionActivitiesLocked(mServices);
            }
            if (mThread == null) {
                // Only update lru and oom-adj if the process is alive. Because it may be called
                // when cleaning up the last activity from handling process died, the dead process
                // should not be added to lru list again.
                return;
            }
            mService.updateLruProcessLocked(this, activityChange, null /* client */);
            if (updateOomAdj) {
                mService.updateOomAdjLocked(this, OomAdjuster.OOM_ADJ_REASON_ACTIVITY);
            }
        }
    }

    /**
     * Returns the total time (in milliseconds) spent executing in both user and system code.
     * Safe to call without lock held.
     */
    @Override
    public long getCpuTime() {
        return mService.mAppProfiler.getCpuTimeForPid(mPid);
    }

    @Override
    public void onStartActivity(int topProcessState, boolean setProfileProc, String packageName,
            long versionCode) {
        synchronized (mService) {
            mWaitingToKill = null;
            if (setProfileProc) {
                synchronized (mService.mAppProfiler.mProfilerLock) {
                    mService.mAppProfiler.setProfileProcLPf(this);
                }
            }
            if (packageName != null) {
                addPackage(packageName, versionCode, mService.mProcessStats);
            }

            // Update oom adj first, we don't want the additional states are involved in this round.
            updateProcessInfo(false /* updateServiceConnectionActivities */,
                    true /* activityChange */, true /* updateOomAdj */);
            setPendingUiClean(true);
            mState.setHasShownUi(true);
            mState.forceProcessStateUpTo(topProcessState);
        }
    }

    @Override
    public void appDied(String reason) {
        synchronized (mService) {
            mService.appDiedLocked(this, reason);
        }
    }

    @Override
    public void setRunningRemoteAnimation(boolean runningRemoteAnimation) {
        if (mPid == Process.myPid()) {
            Slog.wtf(TAG, "system can't run remote animation");
            return;
        }
        synchronized (mService) {
            mState.setRunningRemoteAnimation(runningRemoteAnimation);
        }
    }

    public long getInputDispatchingTimeoutMillis() {
        return mWindowProcessController.getInputDispatchingTimeoutMillis();
    }

    public int getProcessClassEnum() {
        if (mPid == MY_PID) {
            return ServerProtoEnums.SYSTEM_SERVER;
        }
        if (info == null) {
            return ServerProtoEnums.ERROR_SOURCE_UNKNOWN;
        }
        return (info.flags & ApplicationInfo.FLAG_SYSTEM) != 0 ? ServerProtoEnums.SYSTEM_APP :
            ServerProtoEnums.DATA_APP;
    }

    /** Non-private access is for tests only. */
    @VisibleForTesting
    List<ProcessRecord> getLruProcessList() {
        return mService.mProcessList.getLruProcessesLOSP();
    }
}
