Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 4fbf7006 authored by Yisroel Forta's avatar Yisroel Forta Committed by Android (Google) Code Review
Browse files

Merge "Add AppStartInfo object handling" into main

parents 96ef4624 0afc60f7
Loading
Loading
Loading
Loading
+106 −1
Original line number Diff line number Diff line
@@ -27,7 +27,15 @@ import android.os.Parcel;
import android.os.Parcelable;
import android.os.UserHandle;
import android.util.ArrayMap;

import android.util.proto.ProtoInputStream;
import android.util.proto.ProtoOutputStream;
import android.util.proto.WireTypeMismatchException;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.PrintWriter;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
@@ -608,6 +616,103 @@ public final class ApplicationStartInfo implements Parcelable {
                }
            };

    /**
     * Write to a protocol buffer output stream. Protocol buffer message definition at {@link
     * android.app.ApplicationStartInfoProto}
     *
     * @param proto Stream to write the ApplicationStartInfo object to.
     * @param fieldId Field Id of the ApplicationStartInfo as defined in the parent message
     * @hide
     */
    public void writeToProto(ProtoOutputStream proto, long fieldId) throws IOException {
        final long token = proto.start(fieldId);
        proto.write(ApplicationStartInfoProto.PID, mPid);
        proto.write(ApplicationStartInfoProto.REAL_UID, mRealUid);
        proto.write(ApplicationStartInfoProto.PACKAGE_UID, mPackageUid);
        proto.write(ApplicationStartInfoProto.DEFINING_UID, mDefiningUid);
        proto.write(ApplicationStartInfoProto.PROCESS_NAME, mProcessName);
        proto.write(ApplicationStartInfoProto.STARTUP_STATE, mStartupState);
        proto.write(ApplicationStartInfoProto.REASON, mReason);
        if (mStartupTimestampsNs != null && mStartupTimestampsNs.size() > 0) {
            ByteArrayOutputStream timestampsBytes = new ByteArrayOutputStream();
            ObjectOutputStream timestampsOut = new ObjectOutputStream(timestampsBytes);
            timestampsOut.writeObject(mStartupTimestampsNs);
            proto.write(ApplicationStartInfoProto.STARTUP_TIMESTAMPS,
                    timestampsBytes.toByteArray());
        }
        proto.write(ApplicationStartInfoProto.START_TYPE, mStartType);
        if (mStartIntent != null) {
            Parcel parcel = Parcel.obtain();
            mStartIntent.writeToParcel(parcel, 0);
            proto.write(ApplicationStartInfoProto.START_INTENT, parcel.marshall());
            parcel.recycle();
        }
        proto.write(ApplicationStartInfoProto.LAUNCH_MODE, mLaunchMode);
        proto.end(token);
    }

    /**
     * Read from a protocol buffer input stream. Protocol buffer message definition at {@link
     * android.app.ApplicationStartInfoProto}
     *
     * @param proto Stream to read the ApplicationStartInfo object from.
     * @param fieldId Field Id of the ApplicationStartInfo as defined in the parent message
     * @hide
     */
    public void readFromProto(ProtoInputStream proto, long fieldId)
            throws IOException, WireTypeMismatchException, ClassNotFoundException {
        final long token = proto.start(fieldId);
        while (proto.nextField() != ProtoInputStream.NO_MORE_FIELDS) {
            switch (proto.getFieldNumber()) {
                case (int) ApplicationStartInfoProto.PID:
                    mPid = proto.readInt(ApplicationStartInfoProto.PID);
                    break;
                case (int) ApplicationStartInfoProto.REAL_UID:
                    mRealUid = proto.readInt(ApplicationStartInfoProto.REAL_UID);
                    break;
                case (int) ApplicationStartInfoProto.PACKAGE_UID:
                    mPackageUid = proto.readInt(ApplicationStartInfoProto.PACKAGE_UID);
                    break;
                case (int) ApplicationStartInfoProto.DEFINING_UID:
                    mDefiningUid = proto.readInt(ApplicationStartInfoProto.DEFINING_UID);
                    break;
                case (int) ApplicationStartInfoProto.PROCESS_NAME:
                    mProcessName = intern(proto.readString(ApplicationStartInfoProto.PROCESS_NAME));
                    break;
                case (int) ApplicationStartInfoProto.STARTUP_STATE:
                    mStartupState = proto.readInt(ApplicationStartInfoProto.STARTUP_STATE);
                    break;
                case (int) ApplicationStartInfoProto.REASON:
                    mReason = proto.readInt(ApplicationStartInfoProto.REASON);
                    break;
                case (int) ApplicationStartInfoProto.STARTUP_TIMESTAMPS:
                    ByteArrayInputStream timestampsBytes = new ByteArrayInputStream(proto.readBytes(
                            ApplicationStartInfoProto.STARTUP_TIMESTAMPS));
                    ObjectInputStream timestampsIn = new ObjectInputStream(timestampsBytes);
                    mStartupTimestampsNs = (ArrayMap<Integer, Long>) timestampsIn.readObject();
                    break;
                case (int) ApplicationStartInfoProto.START_TYPE:
                    mStartType = proto.readInt(ApplicationStartInfoProto.START_TYPE);
                    break;
                case (int) ApplicationStartInfoProto.START_INTENT:
                    byte[] startIntentBytes = proto.readBytes(
                        ApplicationStartInfoProto.START_INTENT);
                    if (startIntentBytes.length > 0) {
                        Parcel parcel = Parcel.obtain();
                        parcel.unmarshall(startIntentBytes, 0, startIntentBytes.length);
                        parcel.setDataPosition(0);
                        mStartIntent = Intent.CREATOR.createFromParcel(parcel);
                        parcel.recycle();
                    }
                    break;
                case (int) ApplicationStartInfoProto.LAUNCH_MODE:
                    mLaunchMode = proto.readInt(ApplicationStartInfoProto.LAUNCH_MODE);
                    break;
            }
        }
        proto.end(token);
    }

    /** @hide */
    public void dump(@NonNull PrintWriter pw, @Nullable String prefix, @Nullable String seqSuffix,
            @NonNull SimpleDateFormat sdf) {
+42 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2019 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.
 */

syntax = "proto2";
option java_multiple_files = true;

package android.app;

import "frameworks/base/core/proto/android/privacy.proto";
import "frameworks/proto_logging/stats/enums/app/enums.proto";

/**
 * An android.app.ApplicationStartInfo object.
 */
message ApplicationStartInfoProto {
    option (.android.msg_privacy).dest = DEST_AUTOMATIC;

    optional int32 pid = 1;
    optional int32 real_uid = 2;
    optional int32 package_uid = 3;
    optional int32 defining_uid = 4;
    optional string process_name = 5;
    optional AppStartStartupState startup_state = 6;
    optional AppStartReasonCode reason = 7;
    optional bytes startup_timestamps = 8;
    optional AppStartStartType start_type = 9;
    optional bytes start_intent = 10;
    optional AppStartLaunchMode launch_mode = 11;
}
+21 −0
Original line number Diff line number Diff line
@@ -20,6 +20,7 @@ package com.android.server.am;

import "frameworks/base/core/proto/android/app/activitymanager.proto";
import "frameworks/base/core/proto/android/app/appexitinfo.proto";
import "frameworks/base/core/proto/android/app/appstartinfo.proto";
import "frameworks/base/core/proto/android/app/notification.proto";
import "frameworks/base/core/proto/android/app/profilerinfo.proto";
import "frameworks/base/core/proto/android/content/component_name.proto";
@@ -1041,3 +1042,23 @@ message AppsExitInfoProto {
    }
    repeated Package packages = 2;
}

// sync with com.android.server.am.am.ProcessList.java
message AppsStartInfoProto {
    option (.android.msg_privacy).dest = DEST_AUTOMATIC;

    optional int64 last_update_timestamp = 1;
    message Package {
        option (.android.msg_privacy).dest = DEST_AUTOMATIC;

        optional string package_name = 1;
        message User {
            option (.android.msg_privacy).dest = DEST_AUTOMATIC;

            optional int32 uid = 1;
            repeated .android.app.ApplicationStartInfoProto app_start_info = 2;
        }
        repeated User users = 2;
    }
    repeated Package packages = 2;
}
+38 −1
Original line number Diff line number Diff line
@@ -9718,9 +9718,29 @@ public class ActivityManagerService extends IActivityManager.Stub
    public ParceledListSlice<ApplicationStartInfo> getHistoricalProcessStartReasons(
            String packageName, int maxNum, int userId) {
        enforceNotIsolatedCaller("getHistoricalProcessStartReasons");
        // For the simplification, we don't support USER_ALL nor USER_CURRENT here.
        if (userId == UserHandle.USER_ALL || userId == UserHandle.USER_CURRENT) {
            throw new IllegalArgumentException("Unsupported userId");
        }
        final ArrayList<ApplicationStartInfo> results = new ArrayList<ApplicationStartInfo>();
        final int callingPid = Binder.getCallingPid();
        final int callingUid = Binder.getCallingUid();
        mUserController.handleIncomingUser(callingPid, callingUid, userId, true, ALLOW_NON_FULL,
                "getHistoricalProcessStartReasons", null);
        final ArrayList<ApplicationStartInfo> results = new ArrayList<ApplicationStartInfo>();
        if (!TextUtils.isEmpty(packageName)) {
            final int uid = enforceDumpPermissionForPackage(packageName, userId, callingUid,
                        "getHistoricalProcessStartReasons");
            if (uid != INVALID_UID) {
                mProcessList.mAppStartInfoTracker.getStartInfo(
                        packageName, userId, callingPid, maxNum, results);
            }
        } else {
            // If no package name is given, use the caller's uid as the filter uid.
            mProcessList.mAppStartInfoTracker.getStartInfo(
                    packageName, callingUid, callingPid, maxNum, results);
        }
        return new ParceledListSlice<ApplicationStartInfo>(results);
    }
@@ -9729,6 +9749,14 @@ public class ActivityManagerService extends IActivityManager.Stub
    public void setApplicationStartInfoCompleteListener(
            IApplicationStartInfoCompleteListener listener, int userId) {
        enforceNotIsolatedCaller("setApplicationStartInfoCompleteListener");
        // For the simplification, we don't support USER_ALL nor USER_CURRENT here.
        if (userId == UserHandle.USER_ALL || userId == UserHandle.USER_CURRENT) {
            throw new IllegalArgumentException("Unsupported userId");
        }
        final int callingUid = Binder.getCallingUid();
        mProcessList.mAppStartInfoTracker.addStartInfoCompleteListener(listener, callingUid);
    }
@@ -9742,6 +9770,7 @@ public class ActivityManagerService extends IActivityManager.Stub
        }
        final int callingUid = Binder.getCallingUid();
        mProcessList.mAppStartInfoTracker.clearStartInfoCompleteListener(callingUid, true);
    }
    @Override
@@ -10042,6 +10071,8 @@ public class ActivityManagerService extends IActivityManager.Stub
            }
            pw.println();
            if (dumpAll) {
                pw.println("-------------------------------------------------------------------------------");
                mProcessList.mAppStartInfoTracker.dumpHistoryProcessStartInfo(pw, dumpPackage);
                pw.println("-------------------------------------------------------------------------------");
                mProcessList.mAppExitInfoTracker.dumpHistoryProcessExitInfo(pw, dumpPackage);
            }
@@ -10439,6 +10470,12 @@ public class ActivityManagerService extends IActivityManager.Stub
                LockGuard.dump(fd, pw, args);
            } else if ("users".equals(cmd)) {
                dumpUsers(pw);
            } else if ("start-info".equals(cmd)) {
                if (opti < args.length) {
                    dumpPackage = args[opti];
                    opti++;
                }
                mProcessList.mAppStartInfoTracker.dumpHistoryProcessStartInfo(pw, dumpPackage);
            } else if ("exit-info".equals(cmd)) {
                if (opti < args.length) {
                    dumpPackage = args[opti];
+30 −0
Original line number Diff line number Diff line
@@ -272,6 +272,8 @@ final class ActivityManagerShellCommand extends ShellCommand {
                    return runSetWatchHeap(pw);
                case "clear-watch-heap":
                    return runClearWatchHeap(pw);
                case "clear-start-info":
                    return runClearStartInfo(pw);
                case "clear-exit-info":
                    return runClearExitInfo(pw);
                case "bug-report":
@@ -1339,6 +1341,31 @@ final class ActivityManagerShellCommand extends ShellCommand {
        return 0;
    }

    int runClearStartInfo(PrintWriter pw) throws RemoteException {
        mInternal.enforceCallingPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS,
                "runClearStartInfo()");
        String opt;
        int userId = UserHandle.USER_CURRENT;
        String packageName = null;
        while ((opt = getNextOption()) != null) {
            if (opt.equals("--user")) {
                userId = UserHandle.parseUserArg(getNextArgRequired());
            } else {
                packageName = opt;
            }
        }
        if (userId == UserHandle.USER_CURRENT) {
            UserInfo user = mInterface.getCurrentUser();
            if (user == null) {
                return -1;
            }
            userId = user.id;
        }
        mInternal.mProcessList.mAppStartInfoTracker
                .clearHistoryProcessStartInfo(packageName, userId);
        return 0;
    }

    int runClearExitInfo(PrintWriter pw) throws RemoteException {
        mInternal.enforceCallingPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS,
                "runClearExitInfo()");
@@ -4090,6 +4117,7 @@ final class ActivityManagerShellCommand extends ShellCommand {
            pw.println("    s[ervices] [COMP_SPEC ...]: service state");
            pw.println("    allowed-associations: current package association restrictions");
            pw.println("    as[sociations]: tracked app associations");
            pw.println("    start-info [PACKAGE_NAME]: historical process start information");
            pw.println("    exit-info [PACKAGE_NAME]: historical process exit information");
            pw.println("    lmk: stats on low memory killer");
            pw.println("    lru: raw LRU process list");
@@ -4265,6 +4293,8 @@ final class ActivityManagerShellCommand extends ShellCommand {
            pw.println("      above <HEAP-LIMIT> then a heap dump is collected for the user to report.");
            pw.println("  clear-watch-heap");
            pw.println("      Clear the previously set-watch-heap.");
            pw.println("  clear-start-info [--user <USER_ID> | all | current] [package]");
            pw.println("      Clear the process start-info for given package");
            pw.println("  clear-exit-info [--user <USER_ID> | all | current] [package]");
            pw.println("      Clear the process exit-info for given package");
            pw.println("  bug-report [--progress | --telephony]");
Loading