Skip to content

Commit abe91f5

Browse files
authored
Added Android turbo.db SQLite parser plugin (#4880)
1 parent 32ae7ba commit abe91f5

File tree

7 files changed

+172
-0
lines changed

7 files changed

+172
-0
lines changed

plaso/data/formatters/android.yaml

+26
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,32 @@ short_source: 'LOG'
1212
source: 'Android App Usage'
1313
---
1414
type: 'conditional'
15+
data_type: 'android:event:battery'
16+
enumeration_helpers:
17+
- input_attribute: 'charge_type'
18+
output_attribute: 'charge_type_string'
19+
default_value: 'UNKNOWN'
20+
values:
21+
0: 'not charging'
22+
1: 'rapid charging'
23+
2: 'slow charging'
24+
3: 'wireless charging'
25+
- input_attribute: 'battery_saver'
26+
output_attribute: 'battery_saver_string'
27+
default_value: 'UNKNOWN'
28+
values:
29+
1: 'on'
30+
2: 'off'
31+
message:
32+
- 'Battery level: {battery_level}'
33+
- 'Battery saver: {battery_saver_string}'
34+
- 'Charge type: {charge_type_string}'
35+
short_message:
36+
- 'Battery level: {battery_level}'
37+
short_source: 'LOG'
38+
source: 'Android Turbo Battery Events'
39+
---
40+
type: 'conditional'
1541
data_type: 'android:event:call'
1642
enumeration_helpers:
1743
- input_attribute: 'call_type'

plaso/data/presets.yaml

+1
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ parsers:
88
- filestat
99
- sqlite/android_calls
1010
- sqlite/android_sms
11+
- sqlite/android_turbo
1112
- sqlite/android_webview
1213
- sqlite/android_webviewcache
1314
- sqlite/chrome_8_history

plaso/data/timeliner.yaml

+6
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,12 @@ attribute_mappings:
66
description: 'Last Resume Time'
77
place_holder_event: true
88
---
9+
data_type: 'android:event:battery'
10+
attribute_mappings:
11+
- name: 'recorded_time'
12+
description: 'Recorded Time'
13+
place_holder_event: true
14+
---
915
data_type: 'android:event:call'
1016
attribute_mappings:
1117
- name: 'end_time'

plaso/parsers/sqlite_plugins/__init__.py

+1
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
from plaso.parsers.sqlite_plugins import android_hangouts
66
from plaso.parsers.sqlite_plugins import android_sms
77
from plaso.parsers.sqlite_plugins import android_tango
8+
from plaso.parsers.sqlite_plugins import android_turbo
89
from plaso.parsers.sqlite_plugins import android_twitter
910
from plaso.parsers.sqlite_plugins import android_webview
1011
from plaso.parsers.sqlite_plugins import android_webviewcache
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
# -*- coding: utf-8 -*-
2+
"""SQLite parser plugin for Android turbo database files."""
3+
4+
from dfdatetime import posix_time as dfdatetime_posix_time
5+
6+
from plaso.containers import events
7+
from plaso.parsers import sqlite
8+
from plaso.parsers.sqlite_plugins import interface
9+
10+
11+
class AndroidTurboBatteryEvent(events.EventData):
12+
"""Android turbo battery event data.
13+
14+
Attributes:
15+
battery_level (int): Remaining battery level, expressed as a percentage.
16+
battery_saver (int): Indicates if battery saver is turn on.
17+
charge_type (int): Indicates that the device is charging.
18+
recorded_time (dfdatetime.DateTimeValues): date and time the battery event
19+
was recorded.
20+
"""
21+
22+
DATA_TYPE = 'android:event:battery'
23+
24+
def __init__(self):
25+
"""Initializes event data."""
26+
super(AndroidTurboBatteryEvent, self).__init__(data_type=self.DATA_TYPE)
27+
self.battery_level = None
28+
self.battery_saver = None
29+
self.charge_type = None
30+
self.recorded_time = None
31+
32+
33+
class AndroidTurboPlugin(interface.SQLitePlugin):
34+
"""SQLite parser plugin for Android's turbo.db database files."""
35+
36+
NAME = 'android_turbo'
37+
DATA_FORMAT = 'Android turbo SQLite database (turbo.db) file'
38+
39+
REQUIRED_STRUCTURE = {
40+
'battery_event': frozenset([
41+
'timestamp_millis', 'battery_level', 'charge_type', 'battery_saver'])}
42+
43+
QUERIES = [
44+
('SELECT timestamp_millis, battery_level, charge_type, battery_saver '
45+
'FROM battery_event',
46+
'ParseBatteryEventRow')]
47+
48+
SCHEMAS = [{
49+
'android_metadata': 'CREATE TABLE android_metadata (locale TEXT)',
50+
'battery_event': (
51+
'CREATE TABLE battery_event(timestamp_millis INTEGER PRIMARY KEY '
52+
'DESC, battery_level INTEGER, charge_type INTEGER, battery_saver '
53+
'INTEGER, timezone TEXT, place_key INTEGER, FOREIGN KEY(place_key) '
54+
'REFERENCES charging_places(_id))'),
55+
'charging_places': (
56+
'CREATE TABLE charging_places(_id INTEGER PRIMARY KEY, place_name '
57+
'TEXT, place_api_id TEXT, UNIQUE(place_api_id) ON CONFLICT IGNORE)')}]
58+
59+
def ParseBatteryEventRow(self, parser_mediator, query, row, **unused_kwargs):
60+
"""Parses a row from the battery_event table.
61+
62+
Args:
63+
parser_mediator (ParserMediator): mediates interactions between parsers
64+
and other components, such as storage and dfVFS.
65+
query (str): query that created the row.
66+
row (sqlite3.Row): row.
67+
"""
68+
query_hash = hash(query)
69+
70+
event_data = AndroidTurboBatteryEvent()
71+
event_data.battery_level = self._GetRowValue(
72+
query_hash, row, 'battery_level')
73+
event_data.battery_saver = self._GetRowValue(
74+
query_hash, row, 'battery_saver')
75+
event_data.charge_type = self._GetRowValue(query_hash, row, 'charge_type')
76+
77+
timestamp = self._GetRowValue(query_hash, row, 'timestamp_millis')
78+
79+
event_data.recorded_time = dfdatetime_posix_time.PosixTimeInMilliseconds(
80+
timestamp=timestamp)
81+
82+
parser_mediator.ProduceEventData(event_data)
83+
84+
85+
sqlite.SQLiteParser.RegisterPlugin(AndroidTurboPlugin)

test_data/android_turbo.db

188 KB
Binary file not shown.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
#!/usr/bin/env python3
2+
# -*- coding: utf-8 -*-
3+
"""Tests for the Android turbo plugin."""
4+
5+
import unittest
6+
7+
from plaso.parsers.sqlite_plugins import android_turbo
8+
9+
from tests.parsers.sqlite_plugins import test_lib
10+
11+
12+
class AndroidTurboSQLitePluginTest(test_lib.SQLitePluginTestCase):
13+
"""Tests for the Android turbo database plugin."""
14+
15+
def testProcess(self):
16+
"""Tests the Process function on an Android turbo.db file."""
17+
plugin = android_turbo.AndroidTurboPlugin()
18+
storage_writer = self._ParseDatabaseFileWithPlugin(
19+
['android_turbo.db'], plugin)
20+
21+
number_of_event_data = storage_writer.GetNumberOfAttributeContainers(
22+
'event_data')
23+
self.assertEqual(number_of_event_data, 2717)
24+
25+
number_of_warnings = storage_writer.GetNumberOfAttributeContainers(
26+
'extraction_warning')
27+
self.assertEqual(number_of_warnings, 0)
28+
29+
number_of_warnings = storage_writer.GetNumberOfAttributeContainers(
30+
'recovery_warning')
31+
self.assertEqual(number_of_warnings, 0)
32+
33+
expected_event_values = {
34+
'battery_level': 99,
35+
'battery_saver': 2,
36+
'charge_type': 0,
37+
'recorded_time': '2023-05-27T13:06:46.000+00:00'}
38+
39+
event_data = storage_writer.GetAttributeContainerByIndex('event_data', 0)
40+
self.CheckEventData(event_data, expected_event_values)
41+
42+
expected_event_values = {
43+
'battery_level': 54,
44+
'battery_saver': 2,
45+
'charge_type': 1,
46+
'recorded_time': '2023-06-22T11:26:27.000+00:00'}
47+
48+
event_data = storage_writer.GetAttributeContainerByIndex('event_data', 2138)
49+
self.CheckEventData(event_data, expected_event_values)
50+
51+
52+
if __name__ == '__main__':
53+
unittest.main()

0 commit comments

Comments
 (0)