# Copyright (C) 2022 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.
"""Contains tables for relevant for Android."""

from python.generators.trace_processor_table.public import Column as C
from python.generators.trace_processor_table.public import ColumnDoc
from python.generators.trace_processor_table.public import ColumnFlag
from python.generators.trace_processor_table.public import CppAccess
from python.generators.trace_processor_table.public import CppAccessDuration
from python.generators.trace_processor_table.public import CppDouble
from python.generators.trace_processor_table.public import CppInt32
from python.generators.trace_processor_table.public import CppInt64
from python.generators.trace_processor_table.public import CppOptional
from python.generators.trace_processor_table.public import CppString
from python.generators.trace_processor_table.public import CppTableId
from python.generators.trace_processor_table.public import CppUint32
from python.generators.trace_processor_table.public import Table
from python.generators.trace_processor_table.public import TableDoc
from python.generators.trace_processor_table.public import WrappingSqlView

from src.trace_processor.tables.metadata_tables import THREAD_TABLE
from src.trace_processor.tables.track_tables import TRACK_TABLE

ANDROID_LOG_TABLE = Table(
    python_module=__file__,
    class_name="AndroidLogTable",
    sql_name="__intrinsic_android_logs",
    columns=[
        C("ts", CppInt64(), cpp_access=CppAccess.READ),
        C("utid", CppTableId(THREAD_TABLE), cpp_access=CppAccess.READ),
        C("prio", CppUint32(), cpp_access=CppAccess.READ),
        C("tag", CppOptional(CppString()), cpp_access=CppAccess.READ),
        C("msg", CppString(), cpp_access=CppAccess.READ),
    ],
    tabledoc=TableDoc(
        doc='''
          Log entries from Android logcat.

          NOTE: this table is not sorted by timestamp. This is why we omit the
          sorted flag on the ts column.
        ''',
        group='Android',
        columns={
            'ts': 'Timestamp of log entry.',
            'utid': 'Thread writing the log entry.',
            'prio': 'Priority of the log. 3=DEBUG, 4=INFO, 5=WARN, 6=ERROR.',
            'tag': 'Tag of the log entry.',
            'msg': 'Content of the log entry.'
        },
    ),
)

ANDROID_CPU_PER_UID_TRACK_TABLE = Table(
    python_module=__file__,
    class_name="AndroidCpuPerUidTrackTable",
    sql_name="__intrinsic_android_cpu_per_uid_track",
    columns=[
        C("track_id",
          CppTableId(TRACK_TABLE),
          flags=ColumnFlag.SORTED,
          cpp_access=CppAccess.READ),
        C("uid", CppInt64(), cpp_access=CppAccess.READ),
        C("cluster", CppInt64(), cpp_access=CppAccess.READ),
        C("total_cpu_millis", CppInt64(), cpp_access=CppAccess.READ),
    ],
)

ANDROID_GAME_INTERVENTION_LIST_TABLE = Table(
    python_module=__file__,
    class_name='AndroidGameInterventionListTable',
    sql_name='__intrinsic_android_game_intervention_list',
    wrapping_sql_view=WrappingSqlView('android_game_intervention_list'),
    columns=[
        C('package_name', CppString()),
        C('uid', CppInt64()),
        C('current_mode', CppInt32()),
        C('standard_mode_supported', CppInt32()),
        C('standard_mode_downscale', CppOptional(CppDouble())),
        C('standard_mode_use_angle', CppOptional(CppInt32())),
        C('standard_mode_fps', CppOptional(CppDouble())),
        C('perf_mode_supported', CppInt32()),
        C('perf_mode_downscale', CppOptional(CppDouble())),
        C('perf_mode_use_angle', CppOptional(CppInt32())),
        C('perf_mode_fps', CppOptional(CppDouble())),
        C('battery_mode_supported', CppInt32()),
        C('battery_mode_downscale', CppOptional(CppDouble())),
        C('battery_mode_use_angle', CppOptional(CppInt32())),
        C('battery_mode_fps', CppOptional(CppDouble())),
    ],
    tabledoc=TableDoc(
        doc='''
          A table presenting all game modes and interventions
          of games installed on the system.
          This is generated by the game_mode_intervention data-source.
        ''',
        group='Android',
        columns={
            'package_name':
                '''name of the pakcage, e.g. com.google.android.gm.''',
            'uid':
                '''UID processes of this package runs as.''',
            'current_mode':
                '''current game mode the game is running at.''',
            'standard_mode_supported':
                '''bool whether standard mode is supported.''',
            'standard_mode_downscale':
                '''
                    resolution downscaling factor of standard
                    mode.
                ''',
            'standard_mode_use_angle':
                '''bool whether ANGLE is used in standard mode.''',
            'standard_mode_fps':
                '''
                    frame rate that the game is throttled at in standard
                    mode.
                ''',
            'perf_mode_supported':
                '''bool whether performance mode is supported.''',
            'perf_mode_downscale':
                '''resolution downscaling factor of performance mode.''',
            'perf_mode_use_angle':
                '''bool whether ANGLE is used in performance mode.''',
            'perf_mode_fps':
                '''
                    frame rate that the game is throttled at in performance
                    mode.
                ''',
            'battery_mode_supported':
                '''bool whether battery mode is supported.''',
            'battery_mode_downscale':
                '''resolution downscaling factor of battery mode.''',
            'battery_mode_use_angle':
                '''bool whether ANGLE is used in battery mode.''',
            'battery_mode_fps':
                '''
                    frame rate that the game is throttled at in battery
                    mode.
                '''
        },
    ),
)

ANDROID_DUMPSTATE_TABLE = Table(
    python_module=__file__,
    class_name='AndroidDumpstateTable',
    sql_name='__intrinsic_android_dumpstate',
    wrapping_sql_view=WrappingSqlView('android_dumpstate'),
    columns=[
        C('section', CppOptional(CppString())),
        C('service', CppOptional(CppString())),
        C('line', CppString()),
    ],
    tabledoc=TableDoc(
        doc='''
          Dumpsys entries from Android dumpstate.
        ''',
        group='Android',
        columns={
            'section':
                '''name of the dumpstate section.''',
            'service':
                '''
                    name of the dumpsys service. Only present when
                    dumpstate=="dumpsys", NULL otherwise.
                ''',
            'line':
                '''
                    line-by-line contents of the section/service,
                    one row per line.
                '''
        },
    ),
)

ANDROID_MOTION_EVENTS_TABLE = Table(
    python_module=__file__,
    class_name='AndroidMotionEventsTable',
    sql_name='__intrinsic_android_motion_events',
    columns=[
        C('event_id', CppUint32()),
        C('ts', CppInt64()),
        C(
            'arg_set_id',
            CppOptional(CppUint32()),
            cpp_access=CppAccess.READ_AND_LOW_PERF_WRITE,
        ),
        C(
            'base64_proto_id',
            CppOptional(CppUint32()),
            cpp_access=CppAccess.READ_AND_LOW_PERF_WRITE,
            cpp_access_duration=CppAccessDuration.POST_FINALIZATION,
        ),
        C('source', CppOptional(CppUint32())),
        C('action', CppOptional(CppInt64())),
        C('device_id', CppOptional(CppInt64())),
        C('display_id', CppOptional(CppInt64())),
    ],
    tabledoc=TableDoc(
        doc='Contains Android MotionEvents processed by the system',
        group='Android',
        columns={
            'event_id':
                '''
                    The randomly-generated ID associated with each input event processed
                    by Android Framework, used to track the event through the input pipeline.
                ''',
            'ts':
                '''The timestamp of when the input event was processed by the system.''',
            'arg_set_id':
                ColumnDoc(
                    doc='Details of the motion event parsed from the proto message.',
                    joinable='args.arg_set_id'),
            'base64_proto_id':
                'String id for raw proto message',
            'source':
                'Input source e.g. touchscreen, keyboard',
            'action':
                'Input action e.g. move, down',
            'device_id':
                'Device id',
            'display_id':
                'Display id',
        },
    ),
)

ANDROID_KEY_EVENTS_TABLE = Table(
    python_module=__file__,
    class_name='AndroidKeyEventsTable',
    sql_name='__intrinsic_android_key_events',
    columns=[
        C('event_id', CppUint32()),
        C('ts', CppInt64()),
        C(
            'arg_set_id',
            CppOptional(CppUint32()),
            cpp_access=CppAccess.READ_AND_LOW_PERF_WRITE,
        ),
        C(
            'base64_proto_id',
            CppOptional(CppUint32()),
            cpp_access=CppAccess.READ_AND_LOW_PERF_WRITE,
            cpp_access_duration=CppAccessDuration.POST_FINALIZATION,
        ),
        C('source', CppOptional(CppUint32())),
        C('action', CppOptional(CppInt64())),
        C('device_id', CppOptional(CppInt64())),
        C('display_id', CppOptional(CppInt64())),
        C('key_code', CppOptional(CppInt64())),
    ],
    tabledoc=TableDoc(
        doc='Contains Android KeyEvents processed by the system',
        group='Android',
        columns={
            'event_id':
                '''
                    The randomly-generated ID associated with each input event processed
                    by Android Framework, used to track the event through the input pipeline.
                ''',
            'ts':
                '''The timestamp of when the input event was processed by the system.''',
            'arg_set_id':
                ColumnDoc(
                    doc='Details of the key event parsed from the proto message.',
                    joinable='args.arg_set_id'),
            'base64_proto_id':
                'String id for raw proto message',
            'source':
                'Input source e.g. touchscreen, keyboard',
            'action':
                'Input action e.g. move, down',
            'device_id':
                'Device id',
            'display_id':
                'Display id',
            'key_code':
                'Key code',
        },
    ),
)

ANDROID_INPUT_EVENT_DISPATCH_TABLE = Table(
    python_module=__file__,
    class_name='AndroidInputEventDispatchTable',
    sql_name='__intrinsic_android_input_event_dispatch',
    columns=[
        C('event_id', CppUint32()),
        C(
            'arg_set_id',
            CppOptional(CppUint32()),
            cpp_access=CppAccess.READ_AND_LOW_PERF_WRITE,
        ),
        C('vsync_id', CppInt64()),
        C('window_id', CppInt32()),
        C(
            'base64_proto_id',
            CppOptional(CppUint32()),
            cpp_access=CppAccess.READ_AND_LOW_PERF_WRITE,
            cpp_access_duration=CppAccessDuration.POST_FINALIZATION,
        ),
    ],
    tabledoc=TableDoc(
        doc='''
                Contains records of Android input events being dispatched to input windows
                by the Android Framework.
            ''',
        group='Android',
        columns={
            'event_id':
                ColumnDoc(
                    doc='The id of the input event that was dispatched.',
                    joinable='__intrinsic_android_motion_events.event_id'),
            'arg_set_id':
                ColumnDoc(
                    doc='Details of the dispatched event parsed from the proto message.',
                    joinable='args.arg_set_id'),
            'vsync_id':
                '''
                    The id of the vsync during which the Framework made the decision to
                    dispatch this input event, used to identify the state of the input windows
                    when the dispatching decision was made.
                ''',
            'window_id':
                'The id of the window to which the event was dispatched.',
            'base64_proto_id':
                'String id for raw proto message',
        },
    ),
)

ANDROID_USER_LIST_TABLE = Table(
    python_module=__file__,
    class_name='AndroidUserListTable',
    sql_name='__intrinsic_android_user_list',
    columns=[
        C('type', CppString(), cpp_access=CppAccess.READ_AND_LOW_PERF_WRITE),
        C('android_user_id', CppInt64()),
    ],
    tabledoc=TableDoc(
        doc='''
          Metadata about users added on the device
          This is generated by the user_list data-source.
        ''',
        group='Misc',
        columns={
            'type': '''user type eg. SECONDARY''',
            'android_user_id': '''User id on device''',
        }))

ANDROID_AFLAGS_TABLE = Table(
    python_module=__file__,
    class_name='AndroidAflagsTable',
    sql_name='__intrinsic_android_aflags',
    columns=[
        C('ts', CppInt64()),
        C('package', CppString()),
        C('name', CppString()),
        C('flag_namespace', CppString()),
        C('container', CppString()),
        C('value', CppString()),
        C('staged_value', CppOptional(CppString())),
        C('permission', CppString()),
        C('value_picked_from', CppString()),
        C('storage_backend', CppString()),
        C('type', CppString()),
    ],
    tabledoc=TableDoc(
        doc='''
          A table presenting all aconfig flags and their values.
          This is generated by the android.aflags data-source.
        ''',
        group='Android',
        columns={
            'ts': 'Timestamp of the flag snapshot.',
            'package': 'Package of the flag.',
            'name': 'Name of the flag.',
            'flag_namespace': 'Namespace of the flag.',
            'container': 'Container of the flag.',
            'value': 'Current value of the flag.',
            'staged_value': 'Value of the flag after next reboot.',
            'permission': 'Permission of the flag (read-only or read-write).',
            'value_picked_from': 'Source of the current flag value.',
            'storage_backend': 'The storage backend that owns this flag.',
            'type': 'Value type of the flag (boolean or integer).',
        },
    ),
)

# Keep this list sorted.
ALL_TABLES = [
    ANDROID_AFLAGS_TABLE,
    ANDROID_CPU_PER_UID_TRACK_TABLE,
    ANDROID_DUMPSTATE_TABLE,
    ANDROID_GAME_INTERVENTION_LIST_TABLE,
    ANDROID_INPUT_EVENT_DISPATCH_TABLE,
    ANDROID_KEY_EVENTS_TABLE,
    ANDROID_LOG_TABLE,
    ANDROID_MOTION_EVENTS_TABLE,
    ANDROID_USER_LIST_TABLE,
]
