/*
 * Copyright (C) 2024 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

syntax = "proto2";

package android.os.statsd.packagemanager;

import "frameworks/proto_logging/stats/atoms.proto";
import "frameworks/proto_logging/stats/atom_field_options.proto";

option java_package = "com.android.os.packagemanager";
option java_multiple_files = true;

extend Atom {
  optional ComponentStateChangedReported component_state_changed_reported = 863
      [(module) = "framework"];
  optional PackageInstallerSessionReported package_installer_session_reported = 1101
      [(module) = "framework"];
  optional PackageChangedBroadcastReported package_changed_broadcast_reported = 1129
      [(module) = "framework"];
  optional PackageManagerCacheInvalidationReported
      package_manager_cache_invalidation_reported = 1135
      [(module) = "framework"];
  optional InitAppScanReported init_app_scan_reported = 1171
      [(module) = "framework"];
}

/**
 * Logs the status of the component is changed.
 */
message ComponentStateChangedReported {
  // The state of component.
  enum ComponentState {
    // This component is in its default state.
    COMPONENT_STATE_DEFAULT = 0;

    // This component has been explicitly enabled.
    COMPONENT_STATE_ENABLED = 1;

    // This component has been explicitly disabled.
    COMPONENT_STATE_DISABLED = 2;

    // The user has explicitly disabled the component.
    COMPONENT_STATE_DISABLED_USER = 3;

    // This component should be considered, until the
    // point where the user actually wants to use it.
    COMPONENT_STATE_DISABLED_UNTIL_USED = 4;
  }

  // The UID for which the application is active.
  optional int32 uid = 1 [(is_uid) = true];

  // The old state of component.
  optional ComponentState component_old_state = 2;

  // The new state of component.
  optional ComponentState component_new_state = 3;

  // True if it is a launcher component.
  optional bool is_launcher = 4;

  // True if it is for whole app. False if it is for a component.
  optional bool is_for_whole_app = 5;

  // The UID for which the application calls this method.
  optional int32 calling_uid = 6 [(is_uid) = true];
}

/**
 * Records data on package installation sessions, tracking from the installer's initiation via PackageInstaller APIs to completion.
 *
 * Logged from:
 *      frameworks/base/services/core/java/com/android/server/pm/PackageInstallerSession.java
 */
message PackageInstallerSessionReported {
    // --- Basic info section ---

    // ID of the session, can be used to correlate with Play logging metrics.
    optional int32 session_id = 1;
    // User ID for which the createSession API was called.
    optional int32 user_id = 2;
    // UID of the package that creates the installation session.
    optional int32 installer_uid = 3 [(is_uid) = true];
    // ID of the child sessions, if this is a parent session, null otherwise.
    repeated int32 child_session_ids = 4;
    // ID of the parent session, if this is a child session, -1 otherwise.
    optional int32 parent_session_id = 5;

    // --- SessionParams section ---

    // The mode of installation, corresponding to the MODE_* in SessionParams.
    enum Mode {
        MODE_UNSPECIFIED = 0;
        MODE_INVALID = 1;
        MODE_FULL_INSTALL = 2;
        MODE_INHERIT_EXISTING = 3;
    }
    optional Mode mode = 6;
    // The user action requirement, corresponding to USER_ACTION_* in SessionParams.
    enum UserActionRequirement {
        USER_ACTION_UNSPECIFIED = 0;
        USER_ACTION_REQUIRED = 1;
        USER_ACTION_NOT_REQUIRED = 2;
    }
    optional UserActionRequirement user_action_requirement = 7;
    // Installation flags as specified in SessionParams.
    optional int32 install_flags = 8;
    // Installation location, corresponding to the INSTALL_LOCATION_* in SessionParams.
    enum InstallLocation {
        INSTALL_LOCATION_UNSPECIFIED = 0;
        INSTALL_LOCATION_INTERNAL_ONLY = 1;
        INSTALL_LOCATION_PREFER_EXTERNAL = 2;
    }
    optional InstallLocation install_location = 9;
    // Installation reason, corresponding to the INSTALL_REASON_* in SessionParams.
    enum InstallReason {
        INSTALL_REASON_UNSPECIFIED = 0;
        INSTALL_REASON_POLICY = 1;
        INSTALL_REASON_DEVICE_RESTORE = 2;
        INSTALL_REASON_DEVICE_SETUP = 3;
        INSTALL_REASON_USER = 4;
        INSTALL_REASON_ROLLBACK = 5;
    }
    optional InstallReason install_reason = 10;
    // Installation scenario, corresponding to the INSTALL_SCENARIO_* in SessionParams.
    enum InstallScenario {
        INSTALL_SCENARIO_UNSPECIFIED = 0;
        INSTALL_SCENARIO_FAST = 1;
        INSTALL_SCENARIO_BULK = 2;
        INSTALL_SCENARIO_BULK_SECONDARY = 3;
    }
    optional InstallScenario install_senario = 11;
    // isStaged as specified in SessionParams.
    optional bool is_staged = 12;
    // Required installed version code as specified in SessionParams.
    optional int64 required_installed_version_code = 13;
    // Data loader type as specified in SessionParams.
    enum DataLoaderType {
        DATA_LOADER_TYPE_UNSPECIFIED = 0;
        DATA_LOADER_TYPE_STREAMING = 1;
        DATA_LOADER_TYPE_INCREMENTAL = 2;
    }
    optional DataLoaderType data_loader_type = 14;
    // Rollback data policy as specified in SessionParams.
    enum RollbackDataPolicy {
        ROLLBACK_DATA_POLICY_UNSPECIFIED = 0;
        ROLLBACK_DATA_POLICY_RESTORE = 1;
        ROLLBACK_DATA_POLICY_WIPE = 3;
        ROLLBACK_DATA_POLICY_RETAIN = 4;
    }
    optional RollbackDataPolicy rollback_data_policy = 15;
    // Rollback lifetime millis as specified in SessionParams.
    optional int64 rollback_lifetime_millis = 16;
    // Rollback impact level as specified in SessionParams.
    enum RollbackImpactLevel {
        ROLLBACK_USER_IMPACT_UNSPECIFIED = 0;
        ROLLBACK_USER_IMPACT_LOW = 1;
        ROLLBACK_USER_IMPACT_HIGH = 2;
        ROLLBACK_USER_IMPACT_ONLY_MANUAL = 3;
    }
    optional RollbackImpactLevel rollback_impact_level = 17;
    // Force queryable as specified in SessionParams.
    optional bool force_queryable_override = 18;
    // Default application enabled setting as specified in SessionParams.
    optional bool application_enabled_setting_persistent = 19;
    // Whether the session is a multi-package session.
    optional bool is_multi_package = 20;
    // Whether this session required pre-approval.
    optional bool is_pre_approval = 21;
    // Whether the session was for unarchive.
    optional bool is_unarchive = 22;
    // Whether auto install dependencies is enabled.
    optional bool is_auto_install_dependencies_enabled = 23;
    // Total size of the APKs installed for this package, including the base APK and the splits. 0 if this session is for removing splits.
    optional int64 apks_size_bytes = 24;

    // --- Result section ---

    // Installation result as defined in PackageInstaller.java
    enum StatusCode {
        STATUS_UNSPECIFIED = 0;
        STATUS_PENDING_STREAMING = 1;
        STATUS_PENDING_USER_ACTION = 2;
        STATUS_SUCCESS = 3;
        STATUS_FAILURE = 4;
        STATUS_FAILURE_BLOCKED = 5;
        STATUS_FAILURE_ABORTED = 6;
        STATUS_FAILURE_INVALID = 7;
        STATUS_FAILURE_CONFLICT = 8;
        STATUS_FAILURE_STORAGE = 9;
        STATUS_FAILURE_INCOMPATIBLE = 10;
        STATUS_FAILURE_TIMEOUT = 11;
    }
    optional StatusCode status_code = 25;
    // Whether user action was actually required.
    optional bool user_action_required = 26;
    // Whether the session was deleted because it expired.
    optional bool is_expired = 27;

    // --- Performance section ---


    // The duration from session creation to session commit which marks the start of verification and installation. This duration usually reflects the time when the installer writes data, but sometimes the commit might be delayed for various reasons by the installer.
    optional int64 session_idle_duration_millis = 28;
    // The duration between when the session was committed and when the session is complete. This duration includes the verification and the installation durations.
    optional int64 session_commit_duration_millis = 29;
    // The duration it took to extract native libraries.
    optional int64 native_libs_extraction_duration_millis = 30;
    // The duration it took for the session to be verified by package verifier and sufficient verifiers.
    optional int64 package_verification_duration_millis = 31;
    // The duration it took to process and install the package in PackageManager internally.
    optional int64 internal_installation_duration_millis = 32;
    // The duration between when the session was created to when the session has completed.
    optional int64 session_lifetime_duration_millis = 33;

    // --- Additional ADI params session

    // System's default developer verification policy.
    enum DeveloperVerificationPolicy {
        POLICY_UNSPECIFIED = 0;
        POLICY_NONE = 1;
        POLICY_FAIL_OPEN = 2;
        POLICY_FAIL_WARN = 3;
        POLICY_FAIL_CLOSED = 4;
    }
    optional DeveloperVerificationPolicy adi_verification_policy = 34;
    // UID of the verifier module
    optional int32 adi_verifier_uid = 35 [(is_uid) = true];

    // --- ADI result section ---

    // Reason why ADI verification was bypassed.
    // This corresponds to the reason code integer passed from the ADI module to the system,
    // using the DeveloperVerificationSession#reportVerificationBypassed(int) method.
    // Some predefined values are:
    //  0: The verification was bypassed due to unspecified reason.
    //  1: The verification was bypassed because the installation was initialized
    //     from ADB.
    //  2: The verification was bypassed because it could not be performed due to
    //     emergency.
    //  3: The verification was bypassed because the installation was done in a
    //     testing environment.
    optional int32 adi_bypassed_reason = 36;
    // Whether a timeout extension has been requested by the verifier.
    optional bool adi_timeout_extension_requested = 37;
    // Whether the verification session has extension params.
    optional bool adi_has_extension_params = 38;
    // Whether a policy override has been requested by the verifier.
    optional bool adi_verification_policy_override_requested = 39;
    // Policy override value for the session.
    optional DeveloperVerificationPolicy adi_session_policy_override_value = 40;
    // The response from the verifier.
    enum DeveloperVerificationResponse {
        RESPONSE_UNSPECIFIED = 0;
        RESPONSE_COMPLETE_WITH_PASS = 1;
        RESPONSE_COMPLETE_WITH_REJECT = 2;
        RESPONSE_INCOMPLETE_UNKNOWN = 3;
        RESPONSE_INCOMPLETE_NETWORK_UNAVAILABLE = 4;
        RESPONSE_TIMEOUT = 5;
        RESPONSE_MODULE_DISCONNECTED = 6;
        RESPONSE_OTHER = 7;
    }
    optional DeveloperVerificationResponse adi_verifier_response = 41;
    // ASL status
    enum DeveloperVerificationAslStatus {
        ASL_STATUS_UNSPECIFIED = 0;
        ASL_STATUS_GOOD = 1;
        ASL_STATUS_BAD = 2;
    }
    optional DeveloperVerificationAslStatus asl_status = 42;
    // Was use action required for adi.
    optional bool adi_user_action_required = 43;
    // The reason code why adi required user action, which corresponds to the system API DEVELOPER_VERIFICATION_USER_ACTION_NEEDED_REASON codes.
    enum DeveloperVerificationUserActionRequiredReason {
        USER_ACTION_REQUIRED_REASON_UNSPECIFIED = 0;
        USER_ACTION_REQUIRED_REASON_NETWORK_UNAVAILABLE = 1;
        USER_ACTION_REQUIRED_REASON_DEVELOPER_BLOCKED = 2;
        USER_ACTION_REQUIRED_REASON_LITE_VERIFICATION = 3;
        USER_ACTION_REQUIRED_REASON_UNKNOWN = 4;
    }
    optional DeveloperVerificationUserActionRequiredReason adi_user_action_required_reason = 44;
    // User response code, this responds to the system API DEVELOPER_VERIFICATION_USER_RESPONSE codes.
    enum DeveloperVerificationUserResponse {
        USER_RESPONSE_UNSPECIFIED = 0;
        USER_RESPONSE_ERROR = 1;
        USER_RESPONSE_ABORT = 2;
        USER_RESPONSE_RETRY = 3;
        USER_RESPONSE_INSTALL_ANYWAY = 4;
    }
    optional DeveloperVerificationUserResponse adi_user_response = 45;
    // Retry count, if the user selected retry as the response.
    optional int32 adi_retry_count = 46;
    // Whether the adi verification was using the Lite variation.
    optional bool is_adi_lite = 47;
    // Failure reason when the install failed because of ADI, which corresponds to the EXTRA_DEVELOPER_VERIFICATION_FAILURE_REASON codes.
    enum DeveloperVerificationFailureReason {
        DEVELOPER_VERIFICATION_FAILED_REASON_UNSPECIFIED = 0;
        DEVELOPER_VERIFICATION_FAILED_REASON_NETWORK_UNAVAILABLE = 1;
        DEVELOPER_VERIFICATION_FAILED_REASON_DEVELOPER_BLOCKED = 2;
    }
    optional DeveloperVerificationFailureReason adi_verification_failed_reason = 48;

    // Package name of the app to be installed, if a session failed because of ADI verification rejection. Null otherwise.
    optional string adi_failed_package_name = 49;

    // --- Performance section ---

    // Whether onVerificationCancelled was called. It can be true only when a session is abandoned.
    optional bool adi_on_verification_cancelled_called = 50;
    // The duration it took for ADI verification to complete for the session, from when onVerificationRequired is called till when a response is received from the verifier (or timeout)
    optional int64 adi_verification_duration_millis = 51;
    // The duration between onPackageNameAvailable is called till when onVerificationRequired is called. -1 if unapplicable.
    optional int64 adi_verification_prep_duration_millis = 52;
    // The duration between the last onVerificationRetry is called till when a response is received from the verifier (or timeout). -1 if unapplicable.
    optional int64 adi_verification_retry_duration_millis = 53;
    // The duration between then the binding is first started and when the verifier is connected.
    optional int64 adi_verification_connection_millis = 54;

    // Whether the user has responded in the user confirmation dialog.
    optional bool user_response_received = 55;
    // Whether the user has responded in the developer verification confirmation dialog.
    optional bool adi_user_response_received = 56;

    // The UID of the app that was installed or updated if the session was successful, -1 otherwise.
    optional int32 app_uid = 57 [(is_uid) = true];
}

/**
 * Logs the reason of the PACKAGE_CHANGED broadcast is sent.
 *
 * Logged from:
 *      frameworks/base/services/core/java/com/android/server/pm/BroadcastHelper.java
 */
message PackageChangedBroadcastReported {
  // The reason of the PACKAGE_CHANGED broadcast.
  enum PackageChangedReason {
    // The PACKAGE_CHANGED broadcast is sent due to unspecified reason.
    PACKAGE_CHANGED_REASON_UNSPECIFIED = 0;

    // The PACKAGE_CHANGED broadcast is sent due to the component state being changed.
    PACKAGE_CHANGED_REASON_COMPONENT_STATE_CHANGED = 1;

    // The PACKAGE_CHANGED broadcast is sent due to the package state being changed.
    PACKAGE_CHANGED_REASON_PACKAGE_STATE_CHANGED = 2;

    // The PACKAGE_CHANGED broadcast is sent due to the component label icon being changed.
    PACKAGE_CHANGED_REASON_COMPONENT_LABEL_ICON_CHANGED = 3;

    // The PACKAGE_CHANGED broadcast is sent due to the component state being reset to default.
    PACKAGE_CHANGED_REASON_COMPONENT_STATE_RESET = 4;

    // The PACKAGE_CHANGED broadcast is sent due to the mime group being changed.
    PACKAGE_CHANGED_REASON_MIME_GROUP_CHANGED = 5;

    // The PACKAGE_CHANGED broadcast is sent due to an overlay being changed.
    PACKAGE_CHANGED_REASON_OVERLAY_CHANGED = 6;

    // The PACKAGE_CHANGED broadcast is sent due to the static shared library being changed.
    PACKAGE_CHANGED_REASON_STATIC_SHARED_LIBRARY_CHANGED = 7;

    // The PACKAGE_CHANGED broadcast is sent due to testing.
    PACKAGE_CHANGED_REASON_TEST = 8;
  }

  // The UID for which the application calls this method.
  optional int32 calling_uid = 1 [(is_uid) = true];

  // The UID for which the package has been changed. The change included the component of the
  // package or package itself.
  optional int32 changed_uid = 2 [(is_uid) = true];

  // The reason of PACKAGE_CHANGED broadcast.
  optional PackageChangedReason reason = 3;
}

/**
 * Logs when to call PropertyInvalidatedCache invalidation.
 *
 * The event is reported every time when a cache for package manager is invalidated. For
 * example, when a state change happens in any of the packages installed on the device,
 * the getPackageInfoCache will be invalidated and this event will be reported.
 *
 * Based on the existing data, the frequency of such events is on the order of hundreds per day.
 *
 * Logged from:
 *      frameworks/base/services/core/java/com/android/server/pm//PackageManagerService.java
 */
message PackageManagerCacheInvalidationReported {
  // Define what kind of data is stored in the cache.
  enum CacheType {
    // Unspecific what kind of data is stored in the cache.
    CACHE_TYPE_UNSPECIFIED = 0;

    // The query data of ApplicationInfo and PackageInfo are stored in the cache.
    CACHE_TYPE_APPLICATION_AND_PACKAGE_INFO = 1;

    // The query data of packages for UID are stored in the cache.
    CACHE_TYPE_GET_PACKAGES_FOR_UID = 2;
  }

  // Define the reason to call the invalidation.
  enum InvalidationReason {
    // Unspecific when to call the invalidation.
    INVALIDATION_REASON_UNSPECIFIED = 0;

    // When install the apex package.
    INVALIDATION_REASON_INSTALL_APEX_PACKAGE = 1;

    // When delete the package.
    INVALIDATION_REASON_DELETE_PACKAGE = 2;

    // When commit the package.
    INVALIDATION_REASON_INSTALL_PACKAGE = 3;

    // When the onChanged method is called in AppsFilterImpl.
    INVALIDATION_REASON_APP_FILTER_CHANGE = 4;

    // When write the package restrictions.
    INVALIDATION_REASON_WRITE_PACKAGE_RESTRICTIONS = 5;

    // When write the settings.
    INVALIDATION_REASON_WRITE_SETTINGS = 6;

    // When grant implicit access.
    INVALIDATION_REASON_GRANT_IMPLICIT_ACCESS = 7;

    // When initialize the package manager service.
    INVALIDATION_REASON_PACKAGE_MANAGER_SERVICE_INIT = 8;

    // When package manager service schedule write settings.
    INVALIDATION_REASON_SCHEDULE_WRITE_SETTINGS = 9;

    // When package manager service schedule write package list.
    INVALIDATION_REASON_SCHEDULE_WRITE_PACKAGE_LIST = 10;

    // When package manager service schedule write package restrictions.
    INVALIDATION_REASON_SCHEDULE_WRITE_PACKAGE_RESTRICTIONS = 11;

    // When package manager service enable overlay packages.
    INVALIDATION_REASON_ENABLE_OVERLAY_PACKAGES = 12;

    // When package manager service disable package caches.
    INVALIDATION_REASON_DISABLE_PACKAGE_CACHES = 13;

    // When initialize the permission service.
    INVALIDATION_REASON_PERMISSION_SERVICE_INIT = 14;

    // When initialize the permission manager service.
    INVALIDATION_REASON_PERMISSION_MANAGER_SERVICE_INIT = 15;

    // When the permission flag is changed.
    INVALIDATION_REASON_PERMISSION_FLAG_CHANGED = 16;

    // When set shell permission delegate.
    INVALIDATION_REASON_SET_SHELL_PERMISSION_DELEGATE = 17;

    // When remove shell permission delegate.
    INVALIDATION_REASON_REMOVE_SHELL_PERMISSION_DELEGATE = 18;

    // When add override permission state.
    INVALIDATION_REASON_ADD_OVERRIDE_PERMISSION_STATE = 19;

    // When remove override permission state.
    INVALIDATION_REASON_REMOVE_OVERRIDE_PERMISSION_STATE = 20;

    // When clear override permission state.
    INVALIDATION_REASON_CLEAR_OVERRIDE_PERMISSION_STATE = 21;

    // When clear all override permission state.
    INVALIDATION_REASON_CLEAR_ALL_OVERRIDE_PERMISSION_STATE = 22;
  }

  // What kind of data is stored in the cache.
  optional CacheType cache_type = 1;

  // When to call PropertyInvalidatedCache invalidation.
  optional InvalidationReason invalidation_reason = 2;

  // The number of invalidations reported.
  optional int32 count = 3;
}

/**
 * Reports stats on an initial app scan.
 *
 * Logged when a single package is scanned during the initial system boot, or during an OTA update.
 * The metric is only logged for updated system apps, and focuses mostly on the performance and
 * outcome of the signature verification phase.
 *
 * Logged from:
 *      frameworks/base/services/core/java/com/android/server/pm/InstallPackageHelper.java
 */
message InitAppScanReported {

  // True if the package is allow-listed for strict signature checking (for full stack integrity).
  optional bool is_fsi_enabled = 1;

  // Number of APK splits found for the package.
  optional int32 num_apk_splits = 2;

  // Signature scheme versions.
  enum SignatureSchemeVersion {
    // Signature scheme unknown.
    UNKNOWN = 0;

    // JAR signature scheme.
    JAR = 1;

    // SIGNING_BLOCK_V2 signature scheme.
    V2 = 2;

    // SIGNING_BLOCK_V3 signature scheme.
    V3 = 3;

    // SIGNING_BLOCK_V4 signature scheme.
    V4 = 4;
  }

  // Signature scheme version of the package.
  optional SignatureSchemeVersion signature_scheme_version = 3;

  // The total time it took to scan the package, in milliseconds.
  optional int64 total_scan_duration_millis = 4;

  // Signature verification outcome.
  enum InitAppScanOutcome {
    // It is required that the first enum value is 0.
    UNSPECIFIED = 0;

    // The package was scanned successfully.
    SUCCESS = 1;

    // The package had no recognizable signatures.
    FAILURE_NO_CERTIFICATES = 2;

    // The package was signed, but the signature did not match the file content.
    FAILURE_VERIFICATION = 3;

    // The new signature did not match the one from the existing system package.
    FAILURE_UPDATE_INCOMPATIBLE = 4;

    // Split APK was signed with inconsistent certificates.
    FAILURE_INCONSISTENT_CERTIFICATES = 5;

    // A certificate in the APK was malformed or unreadable.
    FAILURE_CERTIFICATE_ENCODING = 6;

    // The package failed a general validation test, e.g. invalid apk, duplicate package, etc.
    FAILURE_SCAN_VALIDATION = 7;

    // The scan failed for a reason not listed above.
    FAILURE_OTHER = 8;
  }

  // The final outcome of the signature verification process for this package.
  optional InitAppScanOutcome init_app_scan_outcome = 5;
}
