Usage Statistics (usagestats) Log Documentation
Introduction
The Usage Statistics service (usagestats) tracks detailed application usage patterns, providing forensic investigators with critical timeline data about user activities. This service records when apps are launched, how long they're used, and user interaction patterns.
Prerequisites
- Android device with USB debugging enabled
- ADB (Android Debug Bridge) installed
- Android 5.0 (API 21) or higher
- Usage access permission enabled on device
Step 1: Enable Usage Access Permission
Before extracting usage statistics, ensure the permission is granted:
bash
# Check if usage stats permission is granted
adb shell dumpsys usagestats | head -20
# If you see "Usage stats access denied", enable it:
# On device: Settings → Security → Usage access → Enable for "Shell"
# Or via ADB (requires user interaction):
adb shell am start -a android.settings.USAGE_ACCESS_SETTINGS
Step 2: Basic Usage Statistics Extraction
Create your working directory and extract usage data:
bash
# Create evidence directory
mkdir usagestats_evidence
cd usagestats_evidence
# Extract complete usage statistics
adb shell dumpsys usagestats > usagestats_full.txt
# Extract specific time periods
adb shell dumpsys usagestats --hours 24 > usagestats_24hours.txt
adb shell dumpsys usagestats --days 7 > usagestats_7days.txt
# Extract different aggregation types
adb shell dumpsys usagestats daily > usagestats_daily.txt
adb shell dumpsys usagestats weekly > usagestats_weekly.txt
adb shell dumpsys usagestats monthly > usagestats_monthly.txt
adb shell dumpsys usagestats yearly > usagestats_yearly.txt
Step 3: Understanding the Output Structure
Open usagestats_full.txt and observe the structure:
DUMP OF SERVICE usagestats:
userId=0
In-memory daily stats
time range: 1705276800000 - 1705363200000 (2024-01-15 00:00 - 2024-01-16 00:00)
packages:
package=com.android.chrome userId=0
totalTimeUsed=3456000 \# 57.6 minutes
lastTimeUsed=1705359842000 \# 2024-01-15 23:04:02
totalTimeForeground=3456000
lastTimeForeground=1705359842000
appLaunchCount=12
package=com.whatsapp userId=0
totalTimeUsed=8765000 \# 146 minutes
lastTimeUsed=1705361245000 \# 2024-01-15 23:27:25
totalTimeForeground=8765000
lastTimeForeground=1705361245000
appLaunchCount=45
events:
time=1705277400000 type=ACTIVITY\_RESUMED package=com.android.launcher3 class=com.android.launcher3.Launcher
time=1705277415000 type=ACTIVITY\_PAUSED package=com.android.launcher3
time=1705277415000 type=ACTIVITY\_RESUMED package=com.whatsapp class=com.whatsapp.HomeActivity
Step 4: First Analysis Exercise
Let's identify the most used apps today:
bash
# Extract today's usage and sort by time
grep -A3 "totalTimeUsed=" usagestats_24hours.txt | \
grep -E "package=|totalTimeUsed=" | \
paste - - | \
sed 's/.*package=//' | \
sed 's/ userId.*totalTimeUsed=/ /' | \
sort -k2 -nr | \
head -10 | \
awk '{
hours \= int($2/3600000)
minutes \= int(($2%3600000)/60000)
printf "%-40s %2dh %2dm\n", $1, hours, minutes
}'
Understanding Key Components
- Package Statistics
totalTimeUsed- Total milliseconds in foregroundlastTimeUsed- Last foreground timestampappLaunchCount- Number of times launchedtotalTimeForeground- Active usage time
Event Types
1 \= ACTIVITY_RESUMED # App came to foreground
2 \= ACTIVITY_PAUSED # App went to background
5 \= CONFIGURATION_CHANGE # Screen rotation, etc.
7 \= USER_INTERACTION # User touched screen
8 \= SHORTCUT_INVOCATION # Shortcut used
11 \= STANDBY_BUCKET_CHANGED # App standby state changed
15 \= SCREEN_INTERACTIVE # Screen turned on
16 \= SCREEN_NON_INTERACTIVE # Screen turned off
- 23 \= ACTIVITY_STOPPED # App stopped
- Time Aggregations
- Daily: Last 7 days
- Weekly: Last 4 weeks
- Monthly: Last 6 months
- Yearly: Last 2 years
Working with Usage Statistics Logs
How to Extract Specific Timeframes
Extract Custom Date Range
bash
# Function to convert date to milliseconds
date_to_ms() {
date -d "$1" +%s000
}
# Extract usage between specific dates
START_DATE=$(date_to_ms "2024-01-10 00:00:00")
END_DATE=$(date_to_ms "2024-01-15 23:59:59")
# Filter events within date range
awk -v start="$START_DATE" -v end="$END_DATE" '
/time=/ {
time \= $0
gsub(/.*time=/, "", time)
gsub(/ .*/, "", time)
if (time >= start && time \<= end) {
print strftime("%Y-%m-%d %H:%M:%S", time/1000), $0
}
}
' usagestats_full.txt > filtered_timerange.txt
Extract Hourly Usage Patterns
bash
# Create hourly usage distribution
grep "type=ACTIVITY_RESUMED" usagestats_full.txt | \
awk '{
match($0, /time=([0-9]+)/, arr)
hour \= strftime("%H", arr[1]/1000)
hours[hour]++
}
END {
for (h=0; h\<24; h++) {
printf "%02d:00 - %02d:59: %d app launches\n", h, h, hours[sprintf("%02d", h)]
}
}' | sort > hourly_usage_pattern.txt
How to Filter for Specific Events
Track Specific App Usage
bash
# Monitor WhatsApp usage patterns
TARGET_APP="com.whatsapp"
# Extract all events for target app
grep "$TARGET_APP" usagestats_full.txt > ${TARGET_APP}_events.txt
# Create usage timeline
awk '/type=ACTIVITY_RESUMED/ {
match($0, /time=([0-9]+)/, start_time)
}
/type=ACTIVITY_PAUSED/ {
match($0, /time=([0-9]+)/, end_time)
if (start_time[1]) {
duration \= (end_time[1] - start_time[1]) / 1000
printf "%s - %s (%d seconds)\n",
strftime("%Y-%m-%d %H:%M:%S", start_time[1]/1000),
strftime("%H:%M:%S", end_time[1]/1000),
duration
delete start_time
}
}' ${TARGET_APP}_events.txt > ${TARGET_APP}_sessions.txt
Identify App Launch Sequences
bash
# Extract app launch sequences (which apps are opened after each other)
awk '
/type=ACTIVITY_RESUMED/ {
match($0, /time=([0-9]+)/, t)
match($0, /package=([^ ]+)/, p)
if (last_pkg && (t[1] - last_time) \< 60000) { # Within 1 minute
sequences[last_pkg " -> " p[1]]++
}
last_pkg \= p[1]
last_time \= t[1]
}
END {
print "Common App Sequences (within 1 minute):"
for (seq in sequences) {
if (sequences[seq] > 2) {
printf "%3d times: %s\n", sequences[seq], seq
}
}
}
' usagestats_full.txt | sort -nr > app_sequences.txt
How to Correlate with Other Logs
Correlate with Screen On/Off Events
bash
# Extract screen events
grep -E "SCREEN_INTERACTIVE|SCREEN_NON_INTERACTIVE" usagestats_full.txt > screen_events.txt
# Combine with app usage
cat screen_events.txt usagestats_full.txt | \
grep -E "SCREEN_|ACTIVITY_RESUMED" | \
sort -k2 -t\= -n | \
awk '
/SCREEN_INTERACTIVE/ {screen="ON"; time=$2; gsub(/.*time=/, "", time); gsub(/ .*/, "", time)}
/SCREEN_NON_INTERACTIVE/ {screen="OFF"; time=$2; gsub(/.*time=/, "", time); gsub(/ .*/, "", time)}
/ACTIVITY_RESUMED/ {
if (screen \== "ON") {
match($0, /package=([^ ]+)/, pkg)
match($0, /time=([0-9]+)/, t)
print strftime("%Y-%m-%d %H:%M:%S", t[1]/1000), "Screen ON - Launched:", pkg[1]
}
}
' > screen_correlation.txt
Cross-Reference with Battery Stats
bash
# Get heavy battery consuming periods
adb shell dumpsys batterystats --charged | \
grep -A10 "Estimated power use" > battery_drain.txt
# Extract usage during battery drain periods
# This helps identify apps causing battery drain
HIGH_DRAIN_START=$(date_to_ms "2024-01-15 14:00:00")
HIGH_DRAIN_END=$(date_to_ms "2024-01-15 16:00:00")
awk -v start="$HIGH_DRAIN_START" -v end="$HIGH_DRAIN_END" '
/package=/ && /totalTimeUsed=/ {
pkg \= $0
gsub(/.*package=/, "", pkg)
gsub(/ .*totalTimeUsed=/, " ", pkg)
gsub(/ .*/, "", pkg)
if ($0 \~ /lastTimeUsed=/) {
match($0, /lastTimeUsed=(\[0-9\]+)/, last)
if (last\[1\] \>= start && last\[1\] \<= end) {
print pkg " active during high battery drain"
}
}
}
' usagestats_full.txt > battery_correlation.txt
How to Identify Anomalies
Detect Unusual Usage Patterns
bash
# Find apps used at unusual hours (2 AM - 5 AM)
awk '
/type=ACTIVITY_RESUMED/ {
match($0, /time=([0-9]+)/, t)
match($0, /package=([^ ]+)/, p)
hour \= strftime("%H", t[1]/1000)
if (hour >= "02" && hour \<= "05") {
unusual[p[1]]++
print strftime("%Y-%m-%d %H:%M:%S", t[1]/1000), p[1]
}
}
END {
print "\nSummary of night usage (2-5 AM):"
for (app in unusual) {
print app ": " unusual[app] " times"
}
}
' usagestats_full.txt > unusual_hours_usage.txt
Identify Hidden App Usage
bash
# Find apps with usage but no launcher activity
# First get apps with usage
grep "package=" usagestats_full.txt | \
grep -v "totalTimeUsed=0" | \
sed 's/.*package=//' | \
sed 's/ .*//' | \
sort -u > used_apps.txt
# Get apps with launcher
adb shell cmd package list packages | \
while read pkg; do
pkg_name=${pkg#package:}
if adb shell dumpsys package $pkg_name | grep -q "android.intent.category.LAUNCHER"; then
echo $pkg_name
fi
done > launcher_apps.txt
# Find apps used but not in launcher
comm -23 used_apps.txt launcher_apps.txt > hidden_active_apps.txt
Usage Statistics Log Structure
Complete Field Definitions
Package Usage Entry Structure
package=[package.name] userId=[user_id]
totalTimeUsed=[milliseconds] # Total foreground time
lastTimeUsed=[timestamp_ms] # Last time in foreground
totalTimeForeground=[milliseconds] # Same as totalTimeUsed
lastTimeForeground=[timestamp_ms] # Same as lastTimeUsed
totalTimeVisible=[milliseconds] # Time visible (Android 10+)
lastTimeVisible=[timestamp_ms] # Last visible time
totalTimeInForeground=[milliseconds] # Legacy field
lastTimeComponentUsed=[timestamp_ms] # Component-level tracking
appLaunchCount=[count] # Number of launches
appStandbyBucket=[bucket_value] # 10=Active, 20=Working, 30=Frequent, 40=Rare
lastJobRunTime=[timestamp_ms] # Last background job
lastSyncTime=[timestamp_ms] # Last sync operation
Event Entry Structure
time=[timestamp_ms] type=[event_type] package=[package.name] class=[component.class] flags=[hex_flags]
Event Types:
1 \= ACTIVITY_RESUMED # Component came to foreground
2 \= ACTIVITY_PAUSED # Component left foreground
3 \= END_OF_DAY # Day boundary crossed
4 \= CONTINUE_PREVIOUS_DAY # Continuation from previous
5 \= CONFIGURATION_CHANGE # Config changed (rotation)
6 \= SYSTEM_INTERACTION # System UI interaction
7 \= USER_INTERACTION # User touched app
8 \= SHORTCUT_INVOCATION # Shortcut launched
9 \= CHOOSER_ACTION # Share/chooser used
10 \= NOTIFICATION_SEEN # Notification viewed
11 \= STANDBY_BUCKET_CHANGED # App standby changed
12 \= NOTIFICATION_INTERRUPTION # Notification appeared
15 \= SCREEN_INTERACTIVE # Screen turned on
16 \= SCREEN_NON_INTERACTIVE # Screen turned off
17 \= KEYGUARD_SHOWN # Lock screen shown
18 \= KEYGUARD_HIDDEN # Device unlocked
23 \= ACTIVITY_STOPPED # Activity fully stopped
26 \= DEVICE_SHUTDOWN # Device shutting down
27 \= DEVICE_STARTUP # Device booted
Configuration Structure
config={
mcc=[mobile_country_code] # e.g., 310 for US
mnc=[mobile_network_code] # e.g., 260 for T-Mobile
locale=[language_region] # e.g., en_US
touchscreen=[type] # 3=finger
keyboard=[type] # 1=nokeys, 2=qwerty
navigation=[type] # 1=nonav, 2=dpad, 3=trackball
orientation=[value] # 1=portrait, 2=landscape
screenLayout=[size_long] # Encoded layout info
colorMode=[wide_hdr] # Color capabilities
uiMode=[type_night] # UI mode settings
screenWidthDp=[width] # Width in dp
screenHeightDp=[height] # Height in dp
smallestScreenWidthDp=[size] # Smallest width
densityDpi=[dpi] # Screen density
}
Data Types and Formats
| Field | Type | Format | Example |
|---|---|---|---|
| Package name | String | Reverse domain | com.example.app |
| Timestamp | Long | Milliseconds since epoch | 1705363200000 |
| Duration | Long | Milliseconds | 3600000 (1 hour) |
| Event type | Integer | Event code | 1 (ACTIVITY_RESUMED) |
| Launch count | Integer | Counter | 42 |
| Standby bucket | Integer | 10/20/30/40/45 | 10 (Active) |
| User ID | Integer | System user | 0 (primary user) |
| Flags | Hex | Bitwise flags | 0x0 |
Retention Periods
| Aggregation Level | Retention Period | Interval Size |
|---|---|---|
| Daily | 7 days | 24 hours |
| Weekly | 4 weeks | 7 days |
| Monthly | 6 months | \~30 days |
| Yearly | 2 years | 365 days |
| Events | Variable | Individual events |
Note: Actual retention may vary by Android version and available storage.
Sample Outputs with Annotations
Normal App Usage Pattern
package=com.android.chrome userId=0
totalTimeUsed=1847000 # 30.7 minutes total
lastTimeUsed=1705359842000 # 2024-01-15 22:04:02
appLaunchCount=8 # Launched 8 times
appStandbyBucket=10 # Active (used recently)
Events:
time=1705340400000 type=ACTIVITY_RESUMED package=com.android.chrome class=org.chromium.chrome.browser.ChromeTabbedActivity
time=1705340580000 type=USER_INTERACTION package=com.android.chrome # User actively using
time=1705340650000 type=ACTIVITY_PAUSED package=com.android.chrome # Switched away
# Duration: 250 seconds (4.2 minutes)
Suspicious Background Activity
package=com.unknown.service userId=0
totalTimeUsed=43200000 # 12 hours (suspicious!)
lastTimeUsed=1705361245000 # Recent activity
appLaunchCount=1 # Only launched once
appStandbyBucket=40 # Rare bucket (but high usage?)
Events:
time=1705318800000 type=ACTIVITY_RESUMED package=com.unknown.service
# No ACTIVITY_PAUSED event - still running?
# No USER_INTERACTION events - running without user input?
Hidden App Usage
package=com.hidden.calculator userId=0 # Calculator app name
totalTimeUsed=7200000 # 2 hours usage
lastTimeUsed=1705280400000 # Used at 3 AM
appLaunchCount=15 # Frequent launches
Events show file manager activities: # Suspicious!
time=1705280400000 type=ACTIVITY_RESUMED class=com.hidden.calculator.FileExplorerActivity
time=1705280420000 type=ACTIVITY_RESUMED class=com.hidden.calculator.PhotoVaultActivity
Quick Reference Commands
bash
# Essential Usage Statistics Commands
adb shell dumpsys usagestats # Full dump
adb shell dumpsys usagestats --hours 24 # Last 24 hours
adb shell dumpsys usagestats --days 7 # Last 7 days
adb shell dumpsys usagestats daily # Daily aggregations
adb shell dumpsys usagestats weekly # Weekly aggregations
adb shell dumpsys usagestats monthly # Monthly aggregations
adb shell dumpsys usagestats yearly # Yearly aggregations
adb shell dumpsys usagestats appstandby # App standby buckets
adb shell dumpsys usagestats eventstats # Raw event data
# Analysis Shortcuts
# Most used apps today
adb shell dumpsys usagestats --hours 24 | grep -B1 "totalTimeUsed=" | grep -v "=0"
# Recent app launches
adb shell dumpsys usagestats | grep "ACTIVITY_RESUMED" | tail -20
# Apps used at specific hour
adb shell dumpsys usagestats | grep "type=1" | grep "2024-01-15 14:"
# App standby states
adb shell dumpsys usagestats appstandby | grep -v "=40" # Non-rare apps
# Screen on/off correlation
adb shell dumpsys usagestats | grep -E "SCREEN_INTERACTIVE|SCREEN_NON_INTERACTIVE"
Understanding Usage Statistics Logs
Why Usage Statistics Logs Exist
Android introduced usage statistics in API 21 (Lollipop) to:
- System Optimization
- Manage app standby and battery optimization
- Predict user behavior for preloading
- Allocate resources based on usage patterns
- User Features
- Digital wellbeing and screen time tracking
- App usage limits and parental controls
- Personalized app suggestions
- Developer Analytics
- App engagement metrics
- Feature usage tracking
- Performance optimization data
How Android Generates Usage Data
Data Collection Flow
User Interaction
↓
Activity Manager notifies Usage Stats Service
↓
├── Component State Changes (foreground/background)
├── User Input Events (touches, clicks)
├── System Events (screen on/off)
└── Configuration Changes
↓
In-Memory Event Buffer
↓
Periodic Flush to Database
↓
Aggregation into Time Buckets
Event Generation Triggers
- App Launch: Creates ACTIVITY_RESUMED event
- App Switch: ACTIVITY_PAUSED + new ACTIVITY_RESUMED
- User Touch: USER_INTERACTION events
- Screen State: SCREEN_INTERACTIVE/NON_INTERACTIVE
- Day Boundary: END_OF_DAY event at midnight
Data Storage Architecture
/data/system/usagestats/
├── 0/ # User 0 directory
│ ├── daily/ # Daily stats
│ │ ├── 1705276800000 # Timestamp files
│ │ └── 1705363200000
│ ├── weekly/ # Weekly aggregations
│ ├── monthly/ # Monthly aggregations
│ ├── yearly/ # Yearly aggregations
│ └── version # Database version
Forensic Significance
Critical Timeline Evidence
- User Presence Indicators
- Screen on/off events prove physical access
- USER_INTERACTION events show active use
- Keystroke patterns indicate user behavior
- App Usage Patterns
- Establishes daily routines
- Shows communication app usage times
- Reveals hidden or suspicious app activity
- Alibi Verification
- Precise timestamps for user activity
- Correlation with claimed activities
- Device usage during critical times
- Behavioral Analysis
- Sleep patterns from usage gaps
- Work/personal app usage separation
- Addiction or obsessive usage patterns
Investigative Applications
| Investigation Type | Relevant Usage Data |
|---|---|
| Timeline Reconstruction | Event timestamps, app sequences |
| User Attribution | Interaction events, usage patterns |
| Communication Analysis | Messaging app usage times |
| Location Correlation | Map app usage before movement |
| Contraband Detection | Hidden app usage, vault apps |
| Child Safety | Age-inappropriate app usage |
| Corporate Espionage | Work app usage outside hours |
Relationship to Other Logs
Direct Correlations
Usage Stats ←→ Battery Stats
└─ Foreground time links to battery drain
Usage Stats ←→ Notification Logs
└─ NOTIFICATION_SEEN events match notifications
Usage Stats ←→ Package Manager
└─ Package names validate installed apps
Usage Stats ←→ Activity Manager
└─ Component names match running activities
Powerful Correlation Techniques
Location Intelligence
bash
# Map app usage before location changes
# Extract map app usage
grep -E "maps|waze|navigation" usagestats_full.txt | \
grep "ACTIVITY_RESUMED" > navigation_usage.txt
# Correlate with location service usage
- adb shell dumpsys location | grep -A5 "Last Known Locations"
Communication Patterns
bash
# Message app usage vs network activity
COMM_APPS="whatsapp|telegram|signal|messages"
grep -E "$COMM_APPS" usagestats_full.txt | \
grep -E "RESUMED|PAUSED" > comm_timeline.txt
# Match with network data transfers
- adb shell dumpsys netstats | grep -E "$COMM_APPS" -A10
Deception Detection
bash
# Find app usage that contradicts user claims
# User claims sleeping 10 PM - 6 AM
awk '
/type=ACTIVITY_RESUMED/ {
match($0, /time=([0-9]+)/, t)
hour \= strftime("%H", t[1]/1000)
if (hour >= "22" || hour \<= "06") {
print strftime("%Y-%m-%d %H:%M:%S", t[1]/1000), $0
}
}
- ' usagestats_full.txt > night_activity.txt
Legal Considerations
Privacy and Consent
- Scope Limitations
- Only shows app-level activity, not content
- Protected by usage access permission
- May require specific warrant language
- User Expectation
- Users often unaware of detailed tracking
- Digital wellbeing features make it visible
- Consider privacy implications in reports
Evidentiary Value
Strengths:
- System-generated, difficult to forge
- Millisecond precision timestamps
- Multiple corroborating data points
- Survives app uninstall
Limitations:
- Can be cleared with factory reset
- Requires usage access permission
- May not capture all background activity
- Multi-user devices complicate attribution
Court Presentation Tips
bash
# Create visual timeline for court
awk '/ACTIVITY_RESUMED/ {
match($0, /time=([0-9]+)/, t)
match($0, /package=([^ ]+)/, p)
printf "%s,%s,start\n", t[1], p[1]
}
/ACTIVITY_PAUSED/ {
match($0, /time=([0-9]+)/, t)
match($0, /package=([^ ]+)/, p)
printf "%s,%s,end\n", t[1], p[1]
}' usagestats_full.txt > timeline_for_visualization.csv
Common Challenges and Solutions
| Challenge | Solution |
|---|---|
| Permission denied | Enable usage access in settings |
| Missing historical data | Check retention periods, may be aged out |
| Time zone confusion | Events in device local time, not UTC |
| Multi-user devices | Filter by userId field |
| Background vs foreground | Check event types carefully |
| App name obfuscation | Cross-reference with package manager |
Advanced Analysis Techniques
User Routine Profiling
python
#!/usr/bin/env python3
# profile_user_routine.py
import re
from collections import defaultdict
from datetime import datetime
# Parse usage events
events \= defaultdict(lambda: defaultdict(int))
with open('usagestats_full.txt', 'r') as f:
for line in f:
if 'ACTIVITY_RESUMED' in line:
time_match \= re.search(r'time=(\d+)', line)
pkg_match \= re.search(r'package=(\S+)', line)
if time\_match and pkg\_match:
timestamp \= int(time\_match.group(1))
package \= pkg\_match.group(1)
dt \= datetime.fromtimestamp(timestamp/1000)
hour \= dt.hour
weekday \= dt.strftime('%A')
events\[weekday\]\[hour\] \+= 1
# Generate routine profile
print("User Activity Profile by Day and Hour:")
days \= ['Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday', 'Sunday']
for day in days:
print(f"\n{day}:")
for hour in range(24):
count \= events[day][hour]
bar \= '█' * (count // 5) # Scale for display
print(f" {hour:02d}:00 {bar} ({count} events)")
Hidden App Detection
bash
# Find calculator/utility apps with suspicious usage patterns
UTILITY_APPS="calculator|flashlight|notepad|clock"
awk -v apps="$UTILITY_APPS" '
$0 \~ apps && /package=/ {
current_app \= $0
gsub(/.*package=/, "", current_app)
gsub(/ .*/, "", current_app)
}
/totalTimeUsed=/ && current_app {
time \= $0
gsub(/.*totalTimeUsed=/, "", time)
gsub(/ .*/, "", time)
if (time > 600000) { # More than 10 minutes
printf "SUSPICIOUS: %s used for %d minutes\n",
current_app, time/60000
}
current_app \= ""
}
' usagestats_full.txt > suspicious_utility_usage.txt
App Dependency Analysis
bash
# Find apps that are always used together
awk '
/ACTIVITY_RESUMED/ {
match($0, /time=([0-9]+)/, t)
match($0, /package=([^ ]+)/, p)
if (last\_time && (t\[1\] \- last\_time) \< 30000\) { \# Within 30 seconds
pair \= (last\_pkg \< p\[1\]) ? last\_pkg "+" p\[1\] : p\[1\] "+" last\_pkg
pairs\[pair\]++
}
last\_time \= t\[1\]
last\_pkg \= p\[1\]
}
END {
print "Frequently Used App Pairs:"
for (pair in pairs) {
if (pairs[pair] > 5) {
print pairs[pair] " times: " pair
}
}
}
' usagestats_full.txt | sort -nr > app_pairs.txt