Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
160 changes: 160 additions & 0 deletions samples/powerplay/QuickStart_Automation.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,160 @@
# PowerPlay Automation Guide

This guide explains how to control the PowerPlay audio player via ADB commands for automated testing of power-efficient audio features (PCM Offload).

## Quick Start

```bash
# Build and install
cd samples/powerplay
../../gradlew installDebug

# Play with PCM Offload enabled
adb shell am start -n com.google.oboe.samples.powerplay/.MainActivity \
--es command play \
--es perf_mode offload

# Monitor status
adb logcat -s PowerPlay:V
```

## Supported ADB Parameters

| Parameter | Type | Description | Example |
| -------------------- | ------- | ---------------------------------------------------------- | ------------------------------ |
| `command` | string | Action: `play`, `pause`, `stop` | `--es command play` |
| `perf_mode` | string | Performance mode: `none`, `lowlat`, `powersave`, `offload` | `--es perf_mode offload` |
| `song_index` | int | Track index (0-2) | `--ei song_index 1` |
| `volume` | int | Volume percentage (0-100) | `--ei volume 50` |
| `background` | boolean | Move app to background after starting | `--ez background true` |
| `duration_ms` | int | Auto-stop after N milliseconds | `--ei duration_ms 10000` |
| `use_mmap` | boolean | Enable/disable MMAP audio path | `--ez use_mmap false` |
| `buffer_frames` | int | Buffer size in frames (offload only) | `--ei buffer_frames 4096` |
| `toggle_offload` | boolean | Enable offload stress test | `--ez toggle_offload true` |
| `toggle_interval_ms` | int | Toggle interval in ms | `--ei toggle_interval_ms 5000` |

## Common Test Scenarios

### Test PCM Offload Mode
```bash
adb shell am start -n com.google.oboe.samples.powerplay/.MainActivity \
--es command play \
--es perf_mode offload
```

### Background Playback Test
```bash
adb shell am start -n com.google.oboe.samples.powerplay/.MainActivity \
--es command play \
--es perf_mode offload \
--ez background true
```

### Timed Playback (10 seconds)
```bash
adb shell am start -n com.google.oboe.samples.powerplay/.MainActivity \
--es command play \
--es perf_mode offload \
--ei duration_ms 10000
```

### Offload Toggle Stress Test
```bash
adb shell am start -n com.google.oboe.samples.powerplay/.MainActivity \
--es command play \
--es perf_mode offload \
--ez toggle_offload true \
--ei toggle_interval_ms 3000
```

### Compare Performance Modes
```bash
# Low Latency
adb shell am start -n com.google.oboe.samples.powerplay/.MainActivity \
--es command play --es perf_mode lowlat

# Power Saving (non-offload)
adb shell am start -n com.google.oboe.samples.powerplay/.MainActivity \
--es command play --es perf_mode powersave

# PCM Offload
adb shell am start -n com.google.oboe.samples.powerplay/.MainActivity \
--es command play --es perf_mode offload
```

### Stop Playback
```bash
adb shell am start -n com.google.oboe.samples.powerplay/.MainActivity \
--es command stop
```

## Machine-Readable Status Logs

The app outputs status to logcat with the `PowerPlay` tag in a parseable format:

```
POWERPLAY_STATUS: PLAYING | SONG=0 | OFFLOAD=true | MMAP=true
POWERPLAY_STATUS: PAUSED
POWERPLAY_STATUS: STOPPED | REASON=AUTO_STOP
```

### Status Values
| Status | Meaning |
| ----------------- | ------------------------------------- |
| `PLAYING` | Audio playback is active |
| `PAUSED` | Audio playback is paused |
| `STOPPED` | Audio playback has stopped |
| `ERROR` | An error occurred |
| `OFFLOAD_REVOKED` | PCM Offload was revoked by the system |

### Log Monitoring
```bash
# Real-time monitoring
adb logcat -s PowerPlay:V

# Filter for status only
adb logcat -s PowerPlay:V | grep "POWERPLAY_STATUS"

# Save to file
adb logcat -s PowerPlay:V > powerplay_test.log
```

## Using the Test Action

For automation scripts, you can also use the dedicated test action:

```bash
adb shell am start -a com.google.oboe.samples.powerplay.TEST \
--es command play \
--es perf_mode offload
```

## Battery Testing

To measure power consumption with offload vs non-offload:

```bash
# Reset battery stats
adb shell dumpsys batterystats --reset

# Run offload test for 5 minutes
adb shell am start -n com.google.oboe.samples.powerplay/.MainActivity \
--es command play \
--es perf_mode offload \
--ez background true \
--ei duration_ms 300000

# Wait for test to complete, then capture stats
adb shell dumpsys batterystats > battery_offload.txt
```

## Troubleshooting

### Offload Not Activating
- Ensure device supports PCM Offload: check `AudioManager.isOffloadedPlaybackSupported()`
- Some devices only support offload with specific sample rates (usually 48kHz)
- Display must be off for some implementations

### App Doesn't Respond to Commands
- Make sure the app is installed: `adb shell pm list packages | grep powerplay`
- Check if activity is exported: `adb shell dumpsys package com.google.oboe.samples.powerplay`
88 changes: 88 additions & 0 deletions samples/powerplay/scripts/test_powerplay.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
#!/bin/bash
# PowerPlay Automation Test Script
# Demonstrates a full test cycle: Open -> Play Offload -> Wait -> Close

set -e

PACKAGE="com.google.oboe.samples.powerplay"
ACTIVITY="${PACKAGE}/.MainActivity"
LOG_TAG="PowerPlay"
TEST_DURATION_MS=10000 # 10 seconds

echo "=== PowerPlay Automation Test ==="
echo ""

# Check device connection
if ! adb devices | grep -q "device$"; then
echo "ERROR: No Android device connected"
exit 1
fi

echo "[1/6] Checking if PowerPlay is installed..."
if ! adb shell pm list packages | grep -q "$PACKAGE"; then
echo "ERROR: PowerPlay is not installed. Please run:"
echo " cd samples/powerplay && ../../gradlew installDebug"
exit 1
fi
echo " ✓ PowerPlay is installed"

echo ""
echo "[2/6] Force-stopping any existing instance..."
adb shell am force-stop "$PACKAGE"
sleep 1
echo " ✓ App stopped"

echo ""
echo "[3/6] Starting playback with PCM Offload mode..."
adb shell am start -n "$ACTIVITY" \
--es command play \
--es perf_mode offload \
--ei duration_ms "$TEST_DURATION_MS" \
--ei volume 75

echo " ✓ Play command sent"

echo ""
echo "[4/6] Monitoring status (waiting for ${TEST_DURATION_MS}ms)..."
echo "---"

# Capture and display logs for the test duration
timeout $((TEST_DURATION_MS / 1000 + 2)) adb logcat -s "$LOG_TAG:V" 2>/dev/null | while read -r line; do
if echo "$line" | grep -q "POWERPLAY_STATUS"; then
echo " LOG: $line"
fi
done || true

echo "---"
echo " ✓ Test duration completed"

echo ""
echo "[5/6] Verifying playback stopped..."
FINAL_STATUS=$(adb logcat -d -s "$LOG_TAG:V" | grep "POWERPLAY_STATUS" | tail -1)
if echo "$FINAL_STATUS" | grep -q "STOPPED"; then
echo " ✓ Playback stopped correctly"
else
echo " ⚠ Last status: $FINAL_STATUS"
fi

echo ""
echo "[6/6] Checking offload status from logs..."
if adb logcat -d -s "$LOG_TAG:V" | grep -q "OFFLOAD=true"; then
echo " ✓ PCM Offload was active during playback"
else
echo " ⚠ PCM Offload may not have been active (device might not support it)"
fi

echo ""
echo "=== Test Complete ==="
echo ""
echo "Full logs saved to: powerplay_test.log"
adb logcat -d -s "$LOG_TAG:V" > powerplay_test.log

echo ""
echo "To run additional tests:"
echo " # Toggle offload stress test"
echo " adb shell am start -n $ACTIVITY --es command play --es perf_mode offload --ez toggle_offload true"
echo ""
echo " # Background playback"
echo " adb shell am start -n $ACTIVITY --es command play --es perf_mode offload --ez background true"
7 changes: 7 additions & 0 deletions samples/powerplay/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,19 @@
<activity
android:name=".MainActivity"
android:exported="true"
android:launchMode="singleTop"
android:theme="@style/Theme.Samples">
<intent-filter>
<action android:name="android.intent.action.MAIN" />

<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>

<!-- Intent filter for automation testing via ADB -->
<intent-filter>
<action android:name="com.google.oboe.samples.powerplay.TEST" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>


Expand Down
41 changes: 41 additions & 0 deletions samples/powerplay/src/main/cpp/PowerPlayJNI.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -275,6 +275,47 @@ Java_com_google_oboe_samples_powerplay_engine_PowerPlayAudioPlayer_getBufferCapa
return player.getBufferCapacityInFrames();
}

/**
* Native (JNI) implementation of PowerPlayAudioPlayer.setVolumeNative()
*/
JNIEXPORT void JNICALL
Java_com_google_oboe_samples_powerplay_engine_PowerPlayAudioPlayer_setVolumeNative(
JNIEnv *env,
jobject,
jfloat volume) {
int32_t currentIndex = player.getCurrentlyPlayingIndex();
if (currentIndex >= 0) {
player.setGain(currentIndex, volume);
return;
}

// Set gain for all tracks if nothing is playing.
for (int i = 0; i < 3; ++i) {
player.setGain(i, volume);
}
}

/**
* Native (JNI) implementation of PowerPlayAudioPlayer.isOffloadedNative()
*/
JNIEXPORT jboolean JNICALL
Java_com_google_oboe_samples_powerplay_engine_PowerPlayAudioPlayer_isOffloadedNative(
JNIEnv *env,
jobject) {
return player.isOffloaded();
}

/**
* Native (JNI) implementation of PowerPlayAudioPlayer.getCurrentlyPlayingIndexNative()
*/
JNIEXPORT jint JNICALL
Java_com_google_oboe_samples_powerplay_engine_PowerPlayAudioPlayer_getCurrentlyPlayingIndexNative(
JNIEnv *env,
jobject) {
return player.getCurrentlyPlayingIndex();
}

#ifdef __cplusplus
}
#endif

8 changes: 8 additions & 0 deletions samples/powerplay/src/main/cpp/PowerPlayMultiPlayer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -239,3 +239,11 @@ int32_t PowerPlayMultiPlayer::getBufferCapacityInFrames() {

return mAudioStream->getBufferCapacityInFrames();
}

bool PowerPlayMultiPlayer::isOffloaded() {
if (mAudioStream == nullptr) {
return false;
}

return mAudioStream->getPerformanceMode() == PerformanceMode::PowerSavingOffloaded;
}
2 changes: 2 additions & 0 deletions samples/powerplay/src/main/cpp/PowerPlayMultiPlayer.h
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,8 @@ class PowerPlayMultiPlayer : public iolib::SimpleMultiPlayer {

int32_t getBufferCapacityInFrames();

bool isOffloaded();

private:
class MyPresentationCallback : public oboe::AudioStreamPresentationCallback {
public:
Expand Down
Loading