Activity Manager (activity) Log Documentation

Learning to Extract Activity Manager Logs

Introduction

The Activity Manager service (activity) is the heart of Android's application lifecycle management. It tracks all running applications, services, processes, and tasks, providing real-time visibility into what's happening on the device. For forensic investigators, it offers crucial evidence about running applications, user interactions, and system state at the time of extraction.

Prerequisites

  • Android device with USB debugging enabled
  • ADB (Android Debug Bridge) installed
  • Understanding of Android components (Activities, Services, Broadcasts)
  • Basic knowledge of process management

Step 1: Understanding Android Components

Before diving into logs, understand what Activity Manager tracks:

bash
# Check current device state
adb shell dumpsys activity | head -50

# Key components tracked:
# - Activities: User interface screens
# - Services: Background operations
# - Processes: Running application processes
# - Tasks: Collections of activities (back stack)
# - Broadcasts: System-wide messages

# - Content Providers: Data sharing components

Step 2: Basic Activity Manager Extraction

Create working directory and extract activity data:

bash
# Create evidence directory
mkdir activity_evidence
cd activity_evidence

# Extract complete activity manager state
adb shell dumpsys activity > activity_full.txt

# Extract specific sections
adb shell dumpsys activity activities > running_activities.txt
adb shell dumpsys activity services > running_services.txt
adb shell dumpsys activity processes > running_processes.txt
adb shell dumpsys activity broadcasts > pending_broadcasts.txt
adb shell dumpsys activity providers > content_providers.txt
adb shell dumpsys activity recents > recent_tasks.txt

# Get current top activity (what user sees)

adb shell dumpsys activity top > current_screen.txt

Step 3: Understanding the Output Structure

Activity Manager output is hierarchical and complex:

ACTIVITY MANAGER ACTIVITIES (dumpsys activity activities)
Display #0 (activities from bottom to top):

Stack #1: type=home mode=fullscreen
Task{7c5d6f8 #1 type=home}
TaskRecord{7c5d6f8 #1 A=com.android.launcher3}
* ActivityRecord{5e8a4d1 u0 com.android.launcher3/.Launcher t1}
app=ProcessRecord{8c5d6f8 2567:com.android.launcher3/u0a57}
state=RESUMED
launchTime=2024-01-15 08:30:15.234
lastVisibleTime=2024-01-15 14:22:31.567

Stack #2: type=standard mode=fullscreen
Task{9a3b2c1 #42 type=standard}
TaskRecord{9a3b2c1 #42 A=com.whatsapp}
* ActivityRecord{7d4e3f2 u0 com.whatsapp/.Main t42}
app=ProcessRecord{6e7f8a9 12345:com.whatsapp/u0a142}
state=PAUSED
launchTime=2024-01-15 14:20:15.789

      pauseTime=2024-01-15 14:22:31.567

Step 4: First Analysis Exercise

Let's identify currently active applications:

bash
# Extract all running activities with their states
grep -E "ActivityRecord|state=|app=ProcessRecord" running_activities.txt | \
awk '
/ActivityRecord/ {
# Extract package and activity name
match($0, /ActivityRecord{[^ ]+ [^ ]+ ([^/]+)\/([^ ]+)/, arr)
package \= arr[1]
activity \= arr[2]
}
/app=ProcessRecord/ {
# Extract PID
match($0, /ProcessRecord{[^ ]+ ([0-9]+):/, arr)
pid \= arr[1]
}
/state=/ {
# Extract state and print
state \= $1
gsub(/state=/, "", state)
if (package) {
printf "%-30s PID:%-6s State: %s\n", package, pid, state
package \= ""
}
}

' | sort -u

Understanding Key Components

  1. Activity States
  2. RESUMED - Currently visible and interactive
  3. PAUSED - Visible but not interactive
  4. STOPPED - Not visible
  5. DESTROYED - Removed from memory
  6. Task Structure
  7. Stack: Container for tasks
  8. Task: Collection of activities
  9. Activity: Single screen/UI component
  10. Process Information
  11. PID: Process identifier
  12. UID: User/app identifier
  13. Process state and importance

Working with Activity Manager Logs

How to Extract Specific Information

Find Currently Visible Application

bash
# Get the focused activity (what user is looking at)
adb shell dumpsys activity activities | \
grep -A2 "mResumedActivity" | \
grep "ActivityRecord" | \
sed 's/.*ActivityRecord{[^ ]* [^ ]* \([^}]*\)}.*/\1/'

# Alternative method - from top
adb shell dumpsys activity top | \
grep "ACTIVITY" | \
head -1 | \

awk '{print $2}'

Track Application Launch History

bash
# Extract recent tasks with timestamps
adb shell dumpsys activity recents | \
grep -E "Recent #|realActivity=|lastActiveTime=" | \
awk '
/Recent #/ {
task_num \= $2
}
/realActivity=/ {
# Extract app name
app \= $1
gsub(/.*realActivity=/, "", app)
gsub(/{|}/, "", app)
}
/lastActiveTime=/ {
# Extract timestamp
time \= $1
gsub(/lastActiveTime=/, "", time)
if (app) {
# Convert to readable time
cmd \= "date -d @" int(time/1000) " +\"%Y-%m-%d %H:%M:%S\""
cmd | getline readable_time
close(cmd)
print readable_time, app
app \= ""
}
}

' | sort -r > recent_app_launches.txt

How to Filter for Specific Events

Find Background Services

bash
# Extract all running services with details
echo "=== Running Background Services \===" > background_services.txt

adb shell dumpsys activity services | \
awk '
/ServiceRecord{/ {
# Extract service info
match($0, /ServiceRecord{[^ ]+ [^ ]+ ([^}]+)}/, arr)
service \= arr[1]
print "\nService:", service
}
/app=ProcessRecord/ {
print " " $0
}
/createTime=/ {
print " " $0
# Convert timestamp
match($0, /createTime=([0-9]+)/, t)
cmd \= "date -d @" int(t[1]/1000) " +\"%Y-%m-%d %H:%M:%S\""
cmd | getline time
close(cmd)
print " Started at:", time
}
/lastActivity=/ {
print " " $0
}
' >> background_services.txt

# Find long-running services
awk '
/createTime=/ {
match($0, /createTime=([0-9]+)/, t)
create_time \= t[1]
}
/lastActivity=/ {
match($0, /lastActivity=([0-9]+)/, t)
last_time \= t[1]
if (create_time && last_time) {
duration \= (last_time - create_time) / 1000 / 60 # minutes
if (duration > 60) {
print prev_service, "running for", duration, "minutes"
}
}
}
/Service:/ {
prev_service \= $0
}

' background_services.txt > long_running_services.txt

Identify Hidden or System Activities

bash
# Find activities without UI (potential hidden operations)
adb shell dumpsys activity activities | \
grep -B5 -A5 "finishing=true\|visible=false" | \
grep -E "ActivityRecord|state=|app=" > hidden_activities.txt

# Extract system-level activities
adb shell dumpsys activity activities | \
grep -B3 -A3 "com.android.systemui\|android:ui\|com.android.settings" | \
grep -v "^--$" > system_activities.txt

# Find activities started by other apps (potential automation)
adb shell dumpsys activity activities | \
grep -B10 "launchedFromPackage=" | \
grep -E "ActivityRecord|launchedFromPackage=" | \
grep -B1 "launchedFromPackage=" | \

grep -v "launchedFromPackage=null" > cross_app_launches.txt

How to Correlate with Other Logs

Correlate with Memory Usage

bash
# Get memory info for running processes
adb shell dumpsys activity processes | \
grep -E "ProcessRecord|lastPss=" > process_memory.txt

# Extract high memory consumers
awk '
/ProcessRecord{/ {
match($0, /ProcessRecord{[^ ]+ [^ ]+:([^/]+)/, arr)
current_app \= arr[1]
}
/lastPss=/ {
match($0, /lastPss=([0-9]+)/, m)
pss_kb \= m[1]
pss_mb \= pss_kb / 1024
if (pss_mb > 100) { # Over 100MB
print current_app, "using", pss_mb, "MB"
}
}

' process_memory.txt > high_memory_apps.txt

bash
# Find apps in foreground during battery drain periods
# First, get foreground app timeline
adb shell dumpsys activity activities | \
grep -E "ActivityRecord.*state=RESUMED|lastVisibleTime=" | \
grep -B1 "state=RESUMED" > foreground_timeline.txt

# Cross-reference with battery stats
echo "Checking foreground apps during high battery drain..."

# Would combine with battery history timestamps

How to Identify Anomalies

Detect Suspicious Process Behavior

bash
# Find processes with unusual characteristics
echo "=== Suspicious Process Detection \==="

# 1. Processes with high restart count
adb shell dumpsys activity processes | \
awk '
/ProcessRecord/ {
process \= $0
}
/crashCount=/ {
match($0, /crashCount=([0-9]+)/, c)
if (c[1] > 5) {
print "High crash count:", process
print " Crashes:", c[1]
}
}
' > suspicious_processes.txt

# 2. Hidden or persistent processes
adb shell dumpsys activity processes | \
grep -B10 -A10 "persistent=true\|hidden=true" | \
grep -E "ProcessRecord|persistent=|hidden=" >> suspicious_processes.txt

# 3. Processes with unusual permissions
adb shell dumpsys activity processes | \
grep -B5 "SYSTEM_UID\|root" | \

grep -v "com.android" >> suspicious_processes.txt

Identify Automation and Bots

bash
# Detect automated behavior patterns
# 1. Rapid activity switching
adb shell dumpsys activity recents | \
grep "lastActiveTime=" | \
awk '{
match($0, /lastActiveTime=([0-9]+)/, t)
times[++count] \= t[1]
}
END {
print "Checking for automation patterns..."
for (i \= 2; i \<= count; i++) {
diff \= times[i-1] - times[i]
if (diff \< 1000 && diff > 0) { # Less than 1 second
print "Rapid switch at:", times[i], "Gap:", diff, "ms"
}
}
}' > automation_detection.txt

# 2. Check for accessibility service abuse
adb shell dumpsys activity services | \
grep -A10 "AccessibilityService" | \

grep -E "ServiceRecord|app=|createTime=" >> automation_detection.txt

Activity Manager Log Structure

Complete Field Definitions

Activity Record Structure

ActivityRecord{hashcode uid package/component taskId}
app=ProcessRecord{hashcode pid:processName/uid}
task=TaskRecord{hashcode #taskId A=affinity}
state=RESUMED|PAUSED|STOPPED|DESTROYED|INITIALIZING|FINISHING
launchedFromUid=uid
launchedFromPackage=package
launchMode=standard|singleTop|singleTask|singleInstance
intent={act=action cat=[categories] flg=flags cmp=component}
frontOfTask=true|false
visible=true|false
sleeping=true|false
finishing=true|false
keysPaused=true|false
inHistory=true|false
persistent=true|false
launchTime=timestamp
lastVisibleTime=timestamp
pauseTime=timestamp
stopTime=timestamp

connections=[ServiceConnection list]

Process Record Structure

ProcessRecord{hashcode pid:processName/uid}
user=userId
uid=appUid
gids=[groupIds]
requiredAbi=armeabi-v7a|arm64-v8a|x86|x86_64
instructionSet=arm|arm64|x86|x86_64
started=true|false
lastActivityTime=timestamp
lastPssTime=timestamp
nextPssTime=timestamp
lastPss=sizeKB lastSwapPss=sizeKB lastCachedPss=sizeKB
cached=true|false empty=true|false
serviceb=true|false serviceHighRam=true|false
notCachedSinceIdle=true|false
initialIdlePss=size trimMemoryLevel=level
memImportance=importance
curProcState=state repProcState=state setProcState=state
curAdj=oomAdj setAdj=oomAdj verifiedAdj=oomAdj
crashCount=count
crashTime=timestamp
restartCount=count
restartTime=timestamp
killedByAm=true|false

killed=true|false

Task Record Structure

TaskRecord{hashcode #taskId A=affinity U=userId}
intent={baseIntent}
origActivity=componentName
realActivity=componentName
autoRemoveRecents=true|false
taskType=home|standard|undefined
isPersistable=true|false
numFullscreen=count
taskDescription={label icon colorPrimary colorBackground}
lastActiveTime=timestamp
lastTimeOnTop=timestamp
lastDescription=description
activities=[ActivityRecord list]
askedCompatMode=true|false
inRecents=true|false
isAvailable=true|false
rootWasReset=true|false
mUserSetupComplete=true|false

effective uid=effectiveUid

Service Record Structure

ServiceRecord{hashcode uid package/component}
app=ProcessRecord{info}
created=true|false
started=true|false
connections={ComponentName -> ArrayList\<ConnectionRecord>}
bindings={Intent.FilterComparison -> IntentBindRecord}
createTime=timestamp
lastActivity=timestamp
restartTime=timestamp
restartDelay=milliseconds
restartCount=count
executeNesting=depth
executeFg=true|false
crashCount=count
isForeground=true|false
foregroundId=notificationId
foregroundNoti=Notification
startRequested=true|false
stopIfKilled=true|false

callStart=true|false

State Definitions and Transitions

Component States Description
Activity INITIALIZING Being created
RESUMED Visible and interactive
PAUSED Visible but not interactive
STOPPED Not visible
FINISHING Being destroyed
DESTROYED Removed from memory
Service Created Service object exists
Started startService() called
Bound bindService() active
Foreground Running with notification
Process Persistent System-critical
Foreground User-visible
Visible Affects what user sees
Service Running service
Cached Kept for performance

Important Flags and Values

Field Values Significance
curAdj -1000 to 999 OOM adjustment (lower \= higher priority)
procState 0-19 Process state (lower \= more important)
memImportance 100-1000 Memory importance level
trimMemoryLevel 5-80 Memory pressure level
crashCount 0+ App stability indicator
persistent true/false System app that shouldn't be killed

Sample Outputs with Annotations

Normal App Usage

Stack #2: type=standard mode=fullscreen
Task{9a3b2c1 #42 type=standard U=0} # User 0, standard task
* ActivityRecord{7d4e3f2 u0 com.whatsapp/.Main t42}
app=ProcessRecord{6e7f8a9 12345:com.whatsapp/u0a142}
state=RESUMED # Currently visible
launchMode=standard # Normal launch mode
visible=true sleeping=false
launchTime=2024-01-15 14:20:15.789

  lastVisibleTime=2024-01-15 14:22:31.567

Suspicious Background Activity

ServiceRecord{3a5b7c9 u0 com.unknown.app/.HiddenService}
app=ProcessRecord{9d8e7f6 23456:com.unknown.app/u0a201}
created=true started=true
createTime=1705274400000 # Started at 3 AM
lastActivity=1705359600000 # Still running after 24 hours!
restartCount=15 # Restarted many times
crashCount=8 # Unstable
isForeground=false # Hidden from user

startRequested=true stopIfKilled=false # Persistent behavior

System UI Manipulation

ActivityRecord{5f6a7b8 u0 com.malware.app/.FakeSystemUI t99}
intent={act=android.intent.action.MAIN
cat=[android.intent.category.HOME] # Pretending to be launcher!
flg=0x10200000} # System flags
task=TaskRecord{8c9d0e1 #99 A=com.android.launcher} # Wrong affinity
state=RESUMED

launchedFromUid=1000 # Claiming system UID launch

Quick Reference Commands

bash
# Essential Activity Manager Commands
adb shell dumpsys activity # Full dump
adb shell dumpsys activity activities # Running activities
adb shell dumpsys activity services # Running services
adb shell dumpsys activity processes # Running processes
adb shell dumpsys activity broadcasts # Pending broadcasts
adb shell dumpsys activity providers # Content providers
adb shell dumpsys activity recents # Recent tasks
adb shell dumpsys activity top # Current top activity
adb shell dumpsys activity oom # OOM adjustments
adb shell dumpsys activity containers # Activity containers

# Analysis Commands
# Current foreground app
adb shell dumpsys activity | grep -A2 "mResumedActivity"

# All running apps
adb shell dumpsys activity processes | grep "ProcessRecord{" | awk '{print $2}'

# Memory usage
adb shell dumpsys activity processes | grep -E "ProcessRecord|lastPss"

# Recent launches
adb shell dumpsys activity recents | grep -E "Recent #|realActivity="

# Background services
adb shell dumpsys activity services | grep "ServiceRecord{" | grep -v "com.android"

# Crash information

adb shell dumpsys activity processes | grep -B5 "crashCount=[1-9]"

Understanding Activity Manager Logs

Why Activity Manager Logs Exist

The Activity Manager is Android's central coordinator for application lifecycle, serving critical functions:

  1. Application Lifecycle Management
  2. Starting and stopping apps
  3. Managing activity stack (back button behavior)
  4. Handling configuration changes (rotation)
  5. Memory management and process killing
  6. System Resource Management
  7. Process prioritization
  8. Memory allocation
  9. CPU scheduling hints
  10. OOM (Out of Memory) killer decisions
  11. Security Enforcement
  12. Permission checking
  13. Component access control
  14. User separation
  15. Intent filtering

How Android Generates Activity Data

Component Lifecycle Flow

User Action (tap app icon)

System Launcher sends Intent

Activity Manager receives Intent

├── Check if process exists
├── Create process if needed
├── Load application code
└── Create activity instance

Activity lifecycle callbacks
├── onCreate()
├── onStart()
├── onResume() → RESUMED state
├── [User interacts]
├── onPause() → PAUSED state
├── onStop() → STOPPED state

└── onDestroy() → DESTROYED state

Data Collection Points

  1. Launch Events: Every startActivity() call logged
  2. State Changes: All lifecycle transitions recorded
  3. Process Events: Creation, death, ANRs tracked
  4. Service Bindings: All IPC connections monitored
  5. Memory Pressure: Trim events and kills logged

Memory Management

Process Importance Hierarchy:
1. Foreground (user-visible)
2. Visible (affects what user sees)
3. Service (doing work)
4. Cached (kept for performance)
5. Empty (candidates for killing)

OOM Adjustment Values:
-1000: System/Persistent
0: Foreground app
100: Visible app
200: Perceptible
300: Backup app
400: Heavy weight
500: Service
600: Home
700: Previous app
800: Service B

900: Cached app

Forensic Significance

Real-Time Device State

Activity Manager provides the most current view of device state:

  1. User Presence Indicators
  2. Current foreground app shows active use
  3. Recent tasks show usage patterns
  4. Activity transitions track user flow
  5. Hidden Operations Detection
  6. Background services reveal hidden apps
  7. Persistent processes show potential malware
  8. Unusual launch patterns indicate automation
  9. System Manipulation
  10. Accessibility service abuse
  11. System UI overlays
  12. Permission escalation attempts
  13. Performance Artifacts
  14. Crash counts indicate unstable apps
  15. Memory usage shows resource abuse
  16. Restart patterns reveal persistence

Investigative Applications

Investigation Type Relevant Activity Data
User Attribution Current activity, recent tasks
Malware Detection Hidden services, crashes, persistence
Timeline Reconstruction Launch times, state transitions
App Behavior Analysis Memory usage, crash patterns
Automation Detection Rapid transitions, accessibility services
Data Exfiltration Background services during inactive periods

Relationship to Other Logs

Activity Manager as Central Hub

Activity Manager ←→ Package Manager
└─ Validates installed components

Activity Manager ←→ Window Manager
└─ Coordinates UI display

Activity Manager ←→ Power Manager
└─ Wake lock attribution

Activity Manager ←→ Content Providers

└─ Manages data access

Powerful Correlation Techniques

App Launch to Network Activity
bash
# Find app launches
LAUNCH_TIME=$(adb shell dumpsys activity recents | \
grep -A3 "com.target.app" | \
grep "lastActiveTime=" | \
sed 's/.*lastActiveTime=//')

# Check network activity around launch
echo "App launched at: $(date -d @$((LAUNCH_TIME/1000)))"

# Query network stats for same period
adb shell dumpsys netstats | \
awk -v time="$LAUNCH_TIME" '
/st=/ && $0 \~ time {
print "Network activity found:", $0

  1. }'

Service Correlation with Battery Drain
bash
# Long-running services
adb shell dumpsys activity services | \
grep -E "ServiceRecord|createTime=" | \
grep -B1 "createTime=" | \
awk '/ServiceRecord/ {service=$0}
/createTime/ {
match($0, /createTime=([0-9]+)/, t)
age \= (systime() * 1000 - t[1]) / 1000 / 60
if (age > 60) print service, "running for", age, "minutes"
}' > long_services.txt

# Cross-reference with battery stats
while read line; do
SERVICE=$(echo "$line" | awk -F'[{}]' '{print $2}' | awk '{print $3}')
echo "Checking battery impact of: $SERVICE"
adb shell dumpsys batterystats | grep -A5 "$SERVICE"

  1. done \< long_services.txt

Hidden App Detection
bash
# Find apps with services but no activities
# Get all services
adb shell dumpsys activity services | \
grep "ServiceRecord{" | \
awk -F'[{}]' '{print $2}' | \
awk '{print $3}' | \
cut -d'/' -f1 | sort -u > service_apps.txt

# Get all activities
adb shell dumpsys activity activities | \
grep "ActivityRecord{" | \
awk -F'[{}]' '{print $2}' | \
awk '{print $3}' | \
cut -d'/' -f1 | sort -u > activity_apps.txt

# Find services without UI

  1. comm -23 service_apps.txt activity_apps.txt > hidden_service_apps.txt

Admissibility Factors

  1. Volatility: Activity data is RAM-based, must be captured quickly
  2. Authenticity: System-generated, difficult to forge
  3. Timeliness: Represents state at exact extraction time
  4. Completeness: May miss historical data

Court Presentation Best Practices

python
#!/usr/bin/env python3
# create_activity_timeline.py

import re
from datetime import datetime
import json

class ActivityTimeline:
def __init__(self, activity_dump):
self.activity_dump \= activity_dump
self.timeline \= []

def parse\_activities(self):  
    """Extract activity launch events"""

    with open(self.activity\_dump, 'r') as f:  
        content \= f.read()

    *\# Find all activity records with times*  
    pattern \= r'ActivityRecord{(\[^}\]+)}.\*?launchTime=(\\d+).\*?state=(\\w+)'

    for match in re.finditer(pattern, content, re.DOTALL):  
        record\_id \= match.group(1)  
        launch\_time \= int(match.group(2))  
        state \= match.group(3)

        *\# Extract app name*  
        app\_match \= re.search(r'(\\S+)/(\\S+)', record\_id)  
        if app\_match:  
            package \= app\_match.group(1)  
            activity \= app\_match.group(2)

            self.timeline.append({  
                'timestamp': datetime.fromtimestamp(launch\_time/1000),  
                'package': package,  
                'activity': activity,  
                'state': state,  
                'type': 'activity\_launch'  
            })

def parse\_services(self):  
    """Extract service start events"""

    pattern \= r'ServiceRecord{\[^}\]+\\s+(\\S+)}.\*?createTime=(\\d+)'

    with open(self.activity\_dump, 'r') as f:  
        for match in re.finditer(pattern, f.read()):  
            service \= match.group(1)  
            create\_time \= int(match.group(2))

            self.timeline.append({  
                'timestamp': datetime.fromtimestamp(create\_time/1000),  
                'service': service,  
                'type': 'service\_start'  
            })

def generate\_report(self):  
    """Create court-friendly timeline"""

    print("ANDROID ACTIVITY TIMELINE REPORT")  
    print("=" \* 50)  
    print(f"Generated: {datetime.now()}\\n")

    *\# Sort by time*  
    self.timeline.sort(key\=lambda x: x\['timestamp'\])

    current\_date \= None  
    for event in self.timeline:  
        event\_date \= event\['timestamp'\].date()

        if event\_date \!= current\_date:  
            print(f"\\n{event\_date}")  
            print("-" \* 30)  
            current\_date \= event\_date

        time\_str \= event\['timestamp'\].strftime("%H:%M:%S")

        if event\['type'\] \== 'activity\_launch':  
            print(f"{time\_str} \- User opened: {event\['package'\]}")  
            print(f"           Screen: {event\['activity'\]}")  
            print(f"           State: {event\['state'\]}")  
        elif event\['type'\] \== 'service\_start':  
            print(f"{time\_str} \- Service started: {event\['service'\]}")

# Usage
timeline \= ActivityTimeline('activity_full.txt')
timeline.parse_activities()
timeline.parse_services()

timeline.generate_report()

Common Challenges and Solutions

Challenge Solution
Volatile data Extract immediately upon device seizure
Large output size Use filtered dumps for specific components
Process churn Multiple extractions to catch changes
System apps noise Filter out com.android.* packages
Timestamp format Convert milliseconds since epoch
State interpretation Reference state transition diagram

Advanced Analysis Techniques

Behavioral Pattern Analysis

bash
#!/bin/bash
# analyze_behavior_patterns.sh

echo "=== User Behavior Pattern Analysis \==="

# 1. App usage sequences
echo -e "\n[+] Common App Sequences:"
adb shell dumpsys activity recents | \
grep "realActivity=" | \
awk '{
gsub(/.*realActivity=/, "")
gsub(/{|}/, "")
if (prev) {
sequences[prev " -> " $0]++
}
prev \= $0
}
END {
for (seq in sequences) {
if (sequences[seq] > 2) {
print sequences[seq] "x:", seq
}
}
}' | sort -nr

# 2. Time-based usage patterns
echo -e "\n[+] Hourly Activity Distribution:"
adb shell dumpsys activity recents | \
grep "lastActiveTime=" | \
awk '{
match($0, /lastActiveTime\=([0-9]+)/, t)
hour \= strftime("%H", t[1]/1000)
hours[hour]++
}
END {

for (h\=0; h\<24; h++) {

Edit
bash
printf "%02d:00 - ", h
for (i\=0; i\<hours[sprintf("%02d",h)]; i++) printf "█"
printf " (%d)\n", hours[sprintf("%02d",h)]
}
}'

# 3. Session duration analysis
echo -e "\n[+] App Session Durations:"
adb shell dumpsys activity activities | \
awk '
/ActivityRecord.*launchTime\=/ {
match($0, /launchTime\=([0-9]+)/, launch)
match($0, /([^\/]+)\//, app)
app_launch[app[1]] \= launch[1]
}
/pauseTime\=/ && app[1] {
match($0, /pauseTime\=([0-9]+)/, pause)
if (app_launch[app[1]]) {
duration \= (pause[1] - app_launch[app[1]]) / 1000 / 60
print app[1], "session:", int(duration), "minutes"
delete app_launch[app[1]]
}
}

' | sort -k3 -nr | head -20

Malware Behavior Detection

python
#!/usr/bin/env python3
# detect_malware_behavior.py

import re
from collections import defaultdict

class MalwareDetector:
def __init__(self, activity_dump):
self.activity_dump \= activity_dump
self.suspicious_patterns \= []

def analyze(self):  
    """Run all malware detection heuristics"""

    with open(self.activity\_dump, 'r') as f:  
        self.content \= f.read()

    self.detect\_hidden\_services()  
    self.detect\_persistent\_processes()  
    self.detect\_accessibility\_abuse()  
    self.detect\_overlay\_attacks()  
    self.detect\_unusual\_launches()

def detect\_hidden\_services(self):  
    """Find services without corresponding activities"""

    *\# Extract all services*  
    services \= re.findall(r'ServiceRecord{\[^}\]+\\s+(\[^/\]+)/(\[^}\]+)}', self.content)  
    service\_packages \= set(s\[0\] for s in services)

    *\# Extract all activities*  
    activities \= re.findall(r'ActivityRecord{\[^}\]+\\s+(\[^/\]+)/(\[^}\]+)}', self.content)  
    activity\_packages \= set(a\[0\] for a in activities)

    *\# Find services without UI*  
    hidden \= service\_packages \- activity\_packages  
    for package in hidden:  
        if not package.startswith('com.android'):  
            self.suspicious\_patterns.append({  
                'type': 'HIDDEN\_SERVICE',  
                'package': package,  
                'risk': 'HIGH',  
                'description': 'Service running without user interface'  
            })

def detect\_persistent\_processes(self):  
    """Find processes that resist termination"""

    pattern \= r'ProcessRecord{\[^}\]+:(\[^/\]+)/\[^}\]+}.\*?restartCount=(\\d+).\*?persistent=(\\w+)'

    for match in re.finditer(pattern, self.content, re.DOTALL):  
        process \= match.group(1)  
        restart\_count \= int(match.group(2))  
        persistent \= match.group(3) \== 'true'

        if restart\_count \> 10 or (persistent and not process.startswith('com.android')):  
            self.suspicious\_patterns.append({  
                'type': 'PERSISTENT\_PROCESS',  
                'process': process,  
                'restart\_count': restart\_count,  
                'persistent': persistent,  
                'risk': 'HIGH' if restart\_count \> 20 else 'MEDIUM',  
                'description': 'Process shows persistence behavior'  
            })

def detect\_accessibility\_abuse(self):  
    """Find potential accessibility service abuse"""

    *\# Look for accessibility services*  
    accessibility\_pattern \= r'ServiceRecord{\[^}\]+\\s+(\[^/\]+)/\[^}\]\*Accessibility\[^}\]\*}'

    for match in re.finditer(accessibility\_pattern, self.content):  
        package \= match.group(1)

        *\# Check if it's a known accessibility app*  
        if package not in \['com.google.android.marvin.talkback',   
                         'com.android.talkback'\]:  
            self.suspicious\_patterns.append({  
                'type': 'ACCESSIBILITY\_SERVICE',  
                'package': package,  
                'risk': 'HIGH',  
                'description': 'Non-standard accessibility service detected'  
            })

def detect\_overlay\_attacks(self):  
    """Find potential overlay/clickjacking attempts"""

    *\# Look for TYPE\_SYSTEM\_ALERT windows*  
    overlay\_pattern \= r'Window{\[^}\]+\\s+(\[^/\]+)/\[^}\]+}.\*?ty=2003'  *\# TYPE\_SYSTEM\_ALERT*

    for match in re.finditer(overlay\_pattern, self.content):  
        package \= match.group(1)  
        if not package.startswith('com.android'):  
            self.suspicious\_patterns.append({  
                'type': 'OVERLAY\_WINDOW',  
                'package': package,  
                'risk': 'HIGH',  
                'description': 'App creating system overlay windows'  
            })

def detect\_unusual\_launches(self):  
    """Find apps launched in unusual ways"""

    *\# Check for apps launched by other apps*  
    launch\_pattern \= r'launchedFromPackage=(\[^\\s\]+).\*?ActivityRecord{\[^}\]+\\s+(\[^/\]+)/'

    for match in re.finditer(launch\_pattern, self.content, re.DOTALL):  
        launcher \= match.group(1)  
        launched \= match.group(2)

        if launcher \!= 'null' and launcher \!= launched:  
            if not launcher.startswith('com.android'):  
                self.suspicious\_patterns.append({  
                    'type': 'CROSS\_APP\_LAUNCH',  
                    'launcher': launcher,  
                    'launched': launched,  
                    'risk': 'MEDIUM',  
                    'description': f'{launcher} launching {launched}'  
                })

def generate\_report(self):  
    """Generate malware detection report"""

    print("=== MALWARE BEHAVIOR DETECTION REPORT \===\\n")

    if not self.suspicious\_patterns:  
        print("No suspicious patterns detected.")  
        return

    *\# Group by risk level*  
    high\_risk \= \[p for p in self.suspicious\_patterns if p\['risk'\] \== 'HIGH'\]  
    medium\_risk \= \[p for p in self.suspicious\_patterns if p\['risk'\] \== 'MEDIUM'\]

    if high\_risk:  
        print("HIGH RISK FINDINGS:")  
        print("-" \* 40)  
        for pattern in high\_risk:  
            print(f"\\n\[{pattern\['type'\]}\]")  
            print(f"Description: {pattern\['description'\]}")  
            for key, value in pattern.items():  
                if key not in \['type', 'description', 'risk'\]:  
                    print(f"{key}: {value}")

    if medium\_risk:  
        print("\\n\\nMEDIUM RISK FINDINGS:")  
        print("-" \* 40)  
        for pattern in medium\_risk:  
            print(f"\\n\[{pattern\['type'\]}\]")  
            print(f"Description: {pattern\['description'\]}")  
            for key, value in pattern.items():  
                if key not in \['type', 'description', 'risk'\]:  
                    print(f"{key}: {value}")

# Usage
detector \= MalwareDetector('activity_full.txt')
detector.analyze()

detector.generate_report()

Process Forensics and Memory Analysis

bash
#!/bin/bash
# process_forensics.sh

echo "=== Process Forensics Analysis \==="

# 1. Extract process memory information
echo -e "\n[+] Process Memory Analysis:"
adb shell dumpsys activity processes | \
awk '
/ProcessRecord{/ {
match($0, /ProcessRecord{[^}]+\s+[0-9]+:([^/]+)/, app)
current_app \= app[1]
}
/lastPss=/ && current_app {
match($0, /lastPss=([0-9]+)/, pss)
match($0, /lastSwapPss=([0-9]+)/, swap)
match($0, /lastCachedPss=([0-9]+)/, cached)

  total\_mb \= (pss\[1\] \+ swap\[1\]) / 1024  
  cached\_mb \= cached\[1\] / 1024

  printf "%-30s Total: %6.1f MB (Cached: %6.1f MB)\\n",   
         current\_app, total\_mb, cached\_mb  
}

' | sort -k3 -nr | head -20

# 2. Find memory leaks (high memory, low activity)
echo -e "\n[+] Potential Memory Leaks:"
adb shell dumpsys activity processes | \
awk '
/ProcessRecord{/ {
process \= $0
high_memory \= 0
}
/lastPss=([0-9]{6,})/ { # Over 100MB
high_memory \= 1
}
/lastActivityTime=/ && high_memory {
match($0, /lastActivityTime=([0-9]+)/, t)
age \= (systime() * 1000 - t[1]) / 1000 / 60
if (age > 30) { # Inactive for 30+ minutes
print process
print " High memory with", int(age), "minutes of inactivity"
}
}
'

# 3. Process relationships and dependencies
echo -e "\n[+] Process Dependencies:"
adb shell dumpsys activity services | \
grep -E "ProcessRecord|connections=" | \
grep -A1 "connections={" | \
grep -v "^--$" | \
awk '
/ProcessRecord/ {
current_proc \= $0
}
/connections=/ && current_proc {
if ($0 !\~ /connections={}/) {
print current_proc
print " Connected to:", $0
}
}

'

Integration with Forensic Workflow

Live Forensics Script

bash
#!/bin/bash
# live_activity_forensics.sh

# Comprehensive activity extraction for forensics

CASE_ID=$1
TIMESTAMP=$(date +%Y%m%d_%H%M%S)
OUTPUT_DIR="activity_forensics_${CASE_ID}_${TIMESTAMP}"

mkdir -p "$OUTPUT_DIR"

echo "Starting Activity Manager Forensic Extraction"
echo "Case ID: $CASE_ID"
echo "Timestamp: $TIMESTAMP"

# 1. Current state snapshot
echo "[+] Capturing current state..."
adb shell dumpsys activity > "$OUTPUT_DIR/activity_complete.txt"
adb shell dumpsys activity top > "$OUTPUT_DIR/current_screen.txt"
adb shell ps -A > "$OUTPUT_DIR/process_list.txt"

# 2. Extract key components
echo "[+] Extracting components..."
for component in activities services processes broadcasts providers recents; do
echo " - Extracting $component"
adb shell dumpsys activity $component > "$OUTPUT_DIR/${component}.txt"
done

# 3. Memory state
echo "[+] Capturing memory state..."
adb shell dumpsys meminfo > "$OUTPUT_DIR/meminfo.txt"
adb shell cat /proc/meminfo > "$OUTPUT_DIR/proc_meminfo.txt"

# 4. Create timeline
echo "[+] Creating timeline..."
cat > "$OUTPUT_DIR/create_timeline.py" \<\< 'EOF'
import re
from datetime import datetime

# Parse recent tasks
with open('recents.txt', 'r') as f:
content \= f.read()

timeline \= []
pattern \= r'Recent #(\d+):.*?realActivity=([^}]+).*?lastActiveTime=(\d+)'

for match in re.finditer(pattern, content, re.DOTALL):
num \= match.group(1)
activity \= match.group(2)
timestamp \= int(match.group(3))

timeline.append({  
    'time': datetime.fromtimestamp(timestamp/1000),  
    'activity': activity,  
    'position': num  
})

# Output timeline
with open('activity_timeline.csv', 'w') as out:
out.write('Timestamp,Position,Activity\n')
for event in sorted(timeline, key=lambda x: x['time'], reverse=True):
out.write(f"{event['time']},{event['position']},{event['activity']}\n")
EOF

cd "$OUTPUT_DIR"
python3 create_timeline.py

# 5. Generate analysis report
echo "[+] Generating analysis report..."
cat > "analysis_report.txt" \<\< EOF
Activity Manager Forensic Analysis Report
\========================================
Case ID: $CASE_ID
Extraction Date: $(date)
Device: $(adb shell getprop ro.product.model)
Android Version: $(adb shell getprop ro.build.version.release)

Current State Summary
--------------------
Current App: $(grep -m1 "mResumedActivity" activity_complete.txt | sed 's/.*ActivityRecord{[^}]*\s\+\([^}]*\)}.*/\1/')

Running Apps: $(grep -c "ProcessRecord{" processes.txt)
Running Services: $(grep -c "ServiceRecord{" services.txt)
Recent Tasks: $(grep -c "Recent #" recents.txt)

High-Risk Findings
-----------------
EOF

# Check for suspicious patterns
grep -E "persistent=true|hidden=true" processes.txt | \
grep -v "com.android" >> analysis_report.txt

echo -e "\nPotential Issues:" >> analysis_report.txt
grep "crashCount=[1-9]" processes.txt >> analysis_report.txt

# 6. Create hashes
echo "[+] Creating integrity hashes..."
find . -name "*.txt" -exec sha256sum {} \; > file_hashes.txt

echo "Extraction complete. Results in: $OUTPUT_DIR"

Conclusion

Activity Manager logs provide critical real-time visibility into Android device state, offering:

  1. Immediate State Capture: What's currently running and visible
  2. Process Intelligence: Memory usage, crashes, and persistence
  3. Service Monitoring: Background operations and hidden activities
  4. User Flow Tracking: App launches and task switching patterns
  5. System Manipulation Detection: Overlays, accessibility abuse, and automation

Key forensic advantages:

  • Volatile but Valuable: Captures current state precisely
  • Behavioral Insights: Reveals app and user behavior patterns
  • Malware Detection: Identifies suspicious process characteristics
  • Timeline Support: Provides launch times and state transitions
  • Cross-Validation: Correlates with other log sources

When combined with persistent logs (package manager, usage stats, battery stats), Activity Manager data completes the forensic picture by showing what was happening at the exact moment of extraction. This makes it invaluable for incident response, malware analysis, and user behavior investigations.

The ephemeral nature of this data means investigators must prioritize its extraction immediately upon device acquisition, as critical evidence about running processes and current state will be lost upon reboot or over time as the system manages memory.