!ls -la $LISA_HOME/libs/utils/platforms/

!cat $LISA_HOME/libs/utils/platforms/hikey.json

"""
Explanation: Target Connectivity
Board specific settings
Boards specific settings can be collected into a JSON
platform description file:
End of explanation
"""


# Check which Android devices are available
!adb devices

ADB_DEVICE = '00b43d0b08a8a4b8'

# Unified configuration dictionary
my_conf = {

    # Target platform
    "platform"    : 'android',

    # Location of external tools (adb, fastboot, systrace, etc)
    # These properties can be used to override the environment variables:
    # ANDROID_HOME and CATAPULT_HOME
    "ANDROID_HOME"  : "/opt/android-sdk-linux",
    "CATAPULT_HOME" : "/home/derkling/Code/catapult",

    # Boards specific settings can be collected into a JSON
    # platform description file, to be placed under:
    # LISA_HOME/libs/utils/platforms
    "board"       : 'hikey',
    
    # If you have multiple Android device connected, here
    # we can specify which one to target
    "device"      : ADB_DEVICE,

    # Folder where all the results will be collected
    "results_dir" : "ReleaseNotes_v16.09",
}

from env import TestEnv

te = TestEnv(my_conf, force_new=True)
target = te.target

"""
Explanation: Single configuration dictionary
End of explanation
"""


from time import sleep

def sample_energy(energy_meter, time_s):
    
    # Reset the configured energy counters
    energy_meter.reset()

    # Run the workload you want to measure
    #
    # In this simple example we just wait some time while the
    # energy counters accumulate power samples
    sleep(time_s)

    # Read and report the measured energy (since last reset)
    return energy_meter.report(te.res_dir)

"""
Explanation: Energy Meters Support

Simple unified interface for multiple acquisition board
exposes two simple methods: reset() and report()
reporting energy consumptions
reports additional info supported by the specific probe,<br>
  e.g. collected samples, stats on current and voltages, etc.
End of explanation
"""


!ls -la /dev/ttyACM*

ACM_DEVICE = '/dev/ttyACM1'

"""
Explanation: Channels mapping support
allows to give a custom name to each channel used



ARM Energy Probe (AEP)
Requirements:
1. the caimin binary tool must be availabe in PATH<br>
   https://github.com/ARM-software/lisa/wiki/Energy-Meters-Requirements#arm-energy-probe-aep
2. the ttyACMx device created once you plug in the AEP device
End of explanation
"""


# Energy Meters Configuration for ARM Energy Probe
aep_conf = {
    'conf' : {
        # Value of the shunt resistor [Ohm] for each channel
        'resistor_values' : [0.010],
        # Device entry assigned to the probe on the host
        'device_entry'    : ACM_DEVICE,
    },
    'channel_map' : {
            'BAT' : 'CH0'
    }
}

from energy import AEP
ape_em = AEP(target, aep_conf, '/tmp')

nrg_report = sample_energy(ape_em, 2)
print nrg_report

!cat $nrg_report.report_file

"""
Explanation: Direct usage
End of explanation
"""


my_conf = {

    # Configure the energy meter to use
    "emeter" : {
        
        # Require usage of an AEP meter
        "instrument" : "aep",
        
        # Configuration parameters require by the AEP device
        "conf" : {
            # Value of the shunt resistor in Ohm
            'resistor_values' : [0.099],
            # Device entry assigned to the probe on the host
            'device_entry'    : ACM_DEVICE,
        },
        
        # Map AEP's channels to logical names (used to generate reports)
        'channel_map' : {
            'BAT' : 'CH0'
        }
    },

    # Other target configurations
    "platform"      : 'android',
    "board"         : 'hikey',
    "device"        : ADB_DEVICE,
    "results_dir"   : "ReleaseNotes_v16.09",
    "ANDROID_HOME"  : "/opt/android-sdk-linux",
    "CATAPULT_HOME" : "/home/derkling/Code/catapult",
}

from env import TestEnv

te = TestEnv(my_conf, force_new=True)

for i in xrange(1,11):
    nrg_report = sample_energy(te.emeter, 1)
    nrg_bat = float(nrg_report.channels['BAT'])
    print "Sample {:2d}: {:.3f}".format(i, nrg_bat)

"""
Explanation: Usage via TestEnv
End of explanation
"""


!ping -c1 baylibre-acme.local | grep '64 bytes'

"""
Explanation: BayLibre's ACME board (ACME)
Requirements:
1. the iio-capture tool must be available in PATH<br>
   https://github.com/ARM-software/lisa/wiki/Energy-Meters-Requirements#iiocapture---baylibre-acme-cape
2. the ACME CAPE should be reacable by network
End of explanation
"""


# Energy Meters Configuration for BayLibre's ACME
acme_conf = {
        "conf" : {
            #'iio-capture' : '/usr/bin/iio-capture',
            #'ip_address' : 'baylibre-acme.local',
        },
        "channel_map" : {
            "Device0" : 0,
            "Device1" : 1,
        },
}

from energy import ACME
acme_em = ACME(target, acme_conf, '/tmp')

nrg_report = sample_energy(acme_em, 2)
print nrg_report

!cat $nrg_report.report_file

"""
Explanation: Direct usage
End of explanation
"""


my_conf = {

    # Configure the energy meter to use
    "emeter" : {
        
        # Require usage of an AEP meter
        "instrument" : "acme",
        
        "conf" : {
            #'iio-capture' : '/usr/bin/iio-capture',
            #'ip_address' : 'baylibre-acme.local',
        },
        'channel_map' : {
            'Device0' : 0,
            'Device1' : 1,
        },
    },

    # Other target configurations
    "platform"      : 'android',
    "board"         : 'hikey',
    "device"        : ADB_DEVICE,
    "results_dir"   : "ReleaseNotes_v16.09",
    "ANDROID_HOME"  : "/opt/android-sdk-linux",
    "CATAPULT_HOME" : "/home/derkling/Code/catapult",
}

from env import TestEnv

te = TestEnv(my_conf, force_new=True)
target = te.target

for i in xrange(1,11):
    nrg_report = sample_energy(te.emeter, 1)
    nrg_bat = float(nrg_report.channels['Device1'])
    print "Sample {:2d}: {:.3f}".format(i, nrg_bat)

"""
Explanation: Usage via TestEnv
End of explanation
"""


from android import System

print "Supported functions:"
for f in dir(System):
    if "__" in f:
        continue
    print "   ", f

"""
Explanation: Android Integration
A new Android library has been added which provides APIs to:
    - simplify the interaction with a device
    - execute interesting workloads and benchmarks
    - make it easy the integration of new workloads and benchmarks
Not intended to replace WA, but instead to provide a Python based<br>
programming interface to automate reproducible experiments on<br>
and Android device.
System control APIs
End of explanation
"""


# logging.getLogger().setLevel(logging.DEBUG)

# Example (use tab to complete)
System.

System.menu(target)
System.back(target)

youtube_apk = System.list_packages(target, 'YouTube')
if youtube_apk:
    System.start_app(target, youtube_apk[0])

logging.getLogger().setLevel(logging.INFO)

"""
Explanation: Capturing main useful actions, for example:
    - ensure we set AIRPLAIN_MODE before measuring scheduler energy
    - provide simple support for input actions (relative swipes)
End of explanation
"""


from android import Screen

print "Supported functions:"
for f in dir(Screen):
    if "__" in f:
        continue
    print "   ", f

# logging.getLogger().setLevel(logging.DEBUG)

# Example (use TAB to complete)
Screen.

Screen.set_brightness(target, auto=False, percent=100)

Screen.set_orientation(target, auto=False, portrait=False)

# logging.getLogger().setLevel(logging.INFO)

"""
Explanation: Screen control APIs
End of explanation
"""


# logging.getLogger().setLevel(logging.DEBUG)

from android import Workload

# Get the list of available workloads
wloads = Workload(te)
wloads.availables(target)

yt = Workload.get(te, name='YouTube')

# Playback big bug bunny for 15s starting from 1:20s
video_id = 'XSGBVzeBUbk'
video_url = "https://youtu.be/{}?t={}s".format(video_id, 80)

# Play video and measure energy consumption
results = yt.run(te.res_dir,
                 video_url, video_duration_s=16,
                 collect='energy')

results

framestats = results[0]
!cat $framestats

"""
Explanation: Workloads Execution
A simple workload class allows to easily add a wrapper for the exection
of a specific Android application.
NOTE: To keep things simple, LISA does not provide APKs installation support.
All the exposes APIs assume that the required packages are already installed<br>
in the target. Whenever a package is missing, LISA reports that and it's up<br>
to the user to install it before using it.
A wrapper class usually requires to specify:
- a package name<br>
  which will be used to verify if the APK is available in the target
- a run method<br>
  which usually exploits the other Android APIs to defined a reproducible
  exection of the specified workload
A reproducible experiment should take care of:
- setups wirelesse connections status
- setup screen orientation and backlight level
- properly collect energy measurements across the sensible part of the experiment
- possibly collect frames statistics whenever available
Example of YouTube integration
Here is an example wrapper which allows to play a YouTube<br>
video for a specified number of seconds:
https://github.com/ARM-software/lisa/blob/master/libs/utils/android/workloads/youtube.py
Example usage of the Workload API
End of explanation
"""


from android import Workload

ui = Workload.get(te, name='UiBench')

# Play video and measure energy consumption
results = ui.run(te.res_dir,
                 ui.test_GlTextureView,
                 duration_s=5,
                 collect='energy')

results

framestats = results[0]
!cat $framestats

"""
Explanation: Benchmarks
Android benchmarks can be integrated as standalone Notebook, like for example
what we provide for PCMark:
    https://github.com/ARM-software/lisa/blob/master/ipynb/android/benchmarks/Android_PCMark.ipynb
Alternatively we are adding other benchmarks as predefined Android workloads.
UiBench support
Here is an example of UiBench workload which can run a specified number
of tests:
End of explanation
"""


# The following exanples uses an HiKey board
ADB_DEVICE = '607A87C400055E6E'

# logging.getLogger().setLevel(logging.DEBUG)

# Unified configuration dictionary
my_conf = {
    
    # Tools required
    "tools" : ['rt-app', 'trace-cmd'],
    
    # RTApp calibration
    #"modules" : ['cpufreq'],
    "rtapp-calib" : {
        "0": 254, "1": 252, "2": 252, "3": 251,
        "4": 251, "5": 252, "6": 251, "7": 251
    },
    
    # FTrace configuration
    "ftrace"  : {
        
        # Events to trace
         "events" : [
            "sched_switch",
            "sched_wakeup",
            "sched_wakeup_new",
            "sched_wakeup_tracking",            
            "sched_stat_wait",
            "sched_overutilized",
            "sched_contrib_scale_f",
            "sched_load_avg_cpu",
            "sched_load_avg_task",
            "sched_tune_config",
            "sched_tune_filter",
            "sched_tune_tasks_update",
            "sched_tune_boostgroup_update",
            "sched_boost_cpu",
            "sched_boost_task",
            "sched_energy_diff",
            "cpu_capacity",
            "cpu_frequency",
            "cpu_idle",
            "walt_update_task_ravg",
            "walt_update_history",
            "walt_migration_update_sum",
         ],
        
#         # Kernel functions to profile
#         "functions" : [
#             "pick_next_task_fair",
#             "select_task_rq_fair",
#             "enqueue_task_fair",
#             "update_curr_fair",
#             "dequeue_task_fair",
#         ],
        
        # Per-CPU buffer configuration
        "buffsize" : 10 * 1024,
    },
        
    # Target platform
    "platform"      : 'android',
    "board"         : 'hikey',
    "device"        : ADB_DEVICE,
    "results_dir"   : "ReleaseNotes_v16.09",
    "ANDROID_HOME"  : "/opt/android-sdk-linux",
    "CATAPULT_HOME" : "/home/derkling/Code/catapult",
}

from env import TestEnv

te = TestEnv(my_conf, force_new=True)
target = te.target

from wlgen import RTA,Ramp

# Let's run a simple RAMP task
rta = RTA(target, 'ramp')
rta.conf(
    kind='profile',
    params = {
        'ramp' : Ramp().get()
    }
);

te.ftrace.start()

target.execute("echo 'my_marker: label=START' > /sys/kernel/debug/tracing/trace_marker",
              as_root=True)
rta.run(out_dir=te.res_dir)
target.execute("echo 'my_marker: label=STOP' > /sys/kernel/debug/tracing/trace_marker",
               as_root=True)

te.ftrace.stop()

trace_file = os.path.join(te.res_dir, 'trace.dat')
te.ftrace.get_trace(trace_file)

"""
Explanation: Improved Trace Analysis support
The Trace module is a wrapper around the TRAPpy library which has been
updated to:

support parsing of systrace file format<br>
  requires catapult locally installed<br>
  https://github.com/catapult-project/catapult
parsing and DataFrame generation for custom events

Create an example trace
NOTE: the cells in this sections are required just to create
    a trace file to be used by the following sections
End of explanation
"""


from trace import Trace

events_to_parse  = my_conf['ftrace']['events']
events_to_parse += ['my_marker'] 

trace = Trace(te.platform, trace_file, events=events_to_parse)

trace.available_events

# Use TAB to complete
trace.data_frame.

rt_tasks = trace.data_frame.rt_tasks()
rt_tasks.head()

lat_df = trace.data_frame.latency_df('ramp')
lat_df.head()

custom_df = trace.data_frame.trace_event('my_marker')
custom_df

ctxsw_df = trace.data_frame.trace_event('sched_switch')
ctxsw_df.head()

"""
Explanation: DataFrame namespace
End of explanation
"""


# Use TAB to complete
trace.analysis.

trace.analysis.tasks.plotTasks(tasks='ramp',
                               signals=['util_avg', 'boosted_util',
                                        'sched_overutilized', 'residencies'])

lat_data = trace.analysis.latency.plotLatency('ramp')

lat_data.T

trace.analysis.frequency.plotClusterFrequencies()

trace.analysis.frequency.plotClusterFrequencyResidency(pct=True, active=True)

trace.analysis.frequency.plotClusterFrequencyResidency(pct=True, active=False)

"""
Explanation: Analysis namespace
End of explanation
"""


