Saturday, January 10, 2026

Inside Android Samsung DHMS: Extracting Device Health, Thermal, and App-Control Data from Android - Part 1

As mentioned in my last post, I am currently researching Samsung system apps on Android.

In this post, I share some of my findings on the Samsung Device Health Management Service (SDHMS).

As the name suggests, SDHMS is responsible for monitoring the overall health of the device — including power consumption, temperature, and system load. It detects abnormal behavior (“anomalies”) in running apps, packages, and processes.

To do this, SDHMS records system health data. Some of this data may be valuable for forensic analysis.

App path: /data/data/com.sec.android.sdhms


Anomalies

First database I examined was anomaly.db

This database stores information about detected anomalies. On my test device, no anomalies were triggered, but one table stood out as particularly interesting to me:

Table "config_history": 

This table has four columns:
  • time - Timestamp of the entry, stored as Unix epoch time in milliseconds
  • config_key - The key of the configuration that was loaded
  • config_version - The version of the loaded configuration
  • reason - The reason why the entry was generated
In my test data, most entries in the reason column are BOOT_COMPLETED. I checked the last five entries, and they indeed correspond to my device reboots.

My results span approximately 1.5 years back, covering the full time span the device was in use. Additionally, I found entries with SYSPACKAGE_REMOVED, which likely indicate that a system package was removed from monitoring. This is less relevant for my current analysis.

From this, I was able to reconstruct a history of device (re)boots for my test device.

Table "anomaly_history":

On my test device, this table does not contain any data.

Based on the available columns, it appears that this table would record information about apps or packages that triggered an anomaly, including the type of anomaly and the timestamp of the event.

Generating meaningful test data for this table is challenging. Nevertheless, it seems designed to provide historical insight into anomalous app behavior when anomalies are detected.

Table "current_config":

I am confident that this table contains the current configuration or a reference to the config file.

  • time - Timestamp of the entry in Unix epoch milliseconds
  • config_key - Key of the configuration loaded
  • config_version - Version of the loaded configuration
  • config_data - The configuration data itself

The config_key and config_version correspond exactly to those referenced in the config_history table.

The config_data column holds a large amount of characters — for my device, 7,413 characters — which appears to be Base64-encoded.

Using CyberChef, it was possible to decode it:

1. From Base64

2. Protobuf Decode

3. JSON -> results in readable, structured data

The decoded content contains a lot of information, such as descriptions of anomaly types configured on the device. While it may not be immediately relevant to my current analysis, knowing how to read and decode this data will perhaps be useful in other cases.

Thermal Log

The next database I examined was thermal_log, which — as the name suggests — is responsible for thermal and system performance logging.

Table "NETSTAT": 

As the name implies, this table stores network usage statistics.

For my test device, data spans approximately 5 days.

  • start_time - The start timestamp of measurement time window, Unix epoch time ms
  • end_time - The end timestamp of measurement time window, Unix epoch time ms
  • package_name - Package Name - related to the package that was measured
  • uid - The App ID on the device
  • net_usage - Bytes transferred in the measurement time window
This table allows you to track network activity per app over time.

Table "CPUSTAT": 

The CPUSTAT table seems to store data on CPU Usage statistics.

Again, for my test device, the data covers roughly 5 days.

  • start_time - The start timestamp of measurement time window, Unix epoch time ms
  • end_time - The end timestamp of measurement time window, Unix epoch time ms
  • uptime - Uptime in seconds
  • cputime - Total CPU time used by process since last boot
  • process_name - Name of the process measured
  • uid - Package ID related to the process
  • pid - Process ID
  • process_usage - CPU time used in measurement time windows

Note: CPU time values are scaled and depend on the number of cores. In general, the higher the process_usage value, the higher the CPU utilization and load generated by the process.

Table "TEMPERATURE":

This table contains temperature sensor data for the device.

For my test device, data covers roughly 5 days.

  • timestamp - The start timestamp of measurement time window, Unix epoch time ms
  • skin_temp - Chassis Temperature
  • ap_temp - Processor Temperature
  • bat_temp - Battery Temperature
  • usb_temp - USB Temperature
  • chg_temp - Charging IC Temperature
  • pa_temp - Pulse Amplifier Temperature (Cell Radio)
  • wifi_temp - WiFi Temperature

Notes on values:

  • Temperatures are stored in degrees Celsius × 10, so divide by 10 to get °C.
  • On devices with different regional settings, values may instead be stored in degrees Fahrenheit.
  • Not all devices provide all sensor data, and some columns may aggregate readings from multiple sensors depending on the Hardware.
In general, this table allows you to get an overview of the device’s thermal state.

Conclusion

In the anomaly.db database, we can extract information such as when the device was rebooted. On my test device this data goes back for 1.5 years - the complete usage time frame of the device.

The thermal_log database provides detailed insights into system activity, including:

  • CPU load generated by apps and processes
  • Network usage per app
  • Device temperature across multiple sensors

On my test device, this data spans roughly 5 days.

What's next?

There is still additional data stored by the app that I haven’t covered in this post. For example:

  • Databases containing battery usage per app for the last 7 days — these require some mapping of numeric package IDs to package names.
  • Log files that record e.g. which app was in use and which SIM card (slot) was active.

I will cover these findings and share further insights in a follow-up post on SDHMS.

I created parsers for ALEAPP for the results shared here - PR is open.





Sunday, January 4, 2026

Android Samsung My Files App: Exploring the File Operations History

I’ve been exploring Samsung apps on Android, and I’d like to share some of my findings. Let’s start with the File Operations History maintained by the Samsung My Files app.

The My Files app keeps a database that logs actions performed on files and folders throughout the system. This database provides a detailed view of user and/or system activity, capturing events such as file creation, movement, copying, and deletion.

Android Version Tested:
Android 16

Test device:
Samsung Galaxy S23

App Version tested:
15.4.01.16

Database Location:
[...]/com.sec.android.app.myfiles/databases/OperationHistory.db


The database can exist both system-wide and per user, for example:
  • /data/data/[...] — system-wide

  • /data/user/0/[...] — default user

  • /data/user/150/[...] — secure folder

By analyzing this database, you can reconstruct file operations done on the system.

The database structure

The most interesting tables in the database are:

1. operation_history:
This table stores summary information about each file operation, including the date and time, type of operation, status, and the number of files or folders involved.

2. operation_history_data
This table contains the detailed information for each operation. It includes one entry per file or folder, specifying the file or folder name, as well as the source and destination paths for the operation.


Table operation_history

  • _id - The primary key, iterating number to identify the operation
  • mDate - Time and date in UTC when the operation was done. Not totally clear if it is the start or the end timestamp
  • mOperationType - Type of Operation - human readable, e.g. MOVE, MOVE_TO_TRASH, RENAME, COPY, DELETE
  • mItemCount - Number of Items the operation is done on. This is the aggregated number of folder and files
  • mFolderCount - Number of folders the operation is done on
  • mPageType - Location in the App from where the operation was triggered.
  • mOperationResult - Result of the operation, not always filled with any data.

Table operation_history_data

  • _id - The primary key, iterating number to identify the file/folder used in operation
  • operation_id - The foreign key, with this we know which operation from the operation_history is related to this line
  • src_path - Source path of the file or folder. Has different meanings for operation. E.g. CREATE_FOLDER -> it is the folder where the new folder is created in
  • src_file_id - Always identical with src_path in my test data
  • dst_path - Destination path of the file or folder. E.g. the file that is created. Can be empty for operations - e.g. for DELETE or EMPTY_TRASH
  • dst_file_id - Always identical with the dst_path in my test data
  • file_type - Decimal number - meaning currently not totally clear, seems to be based on some MIME type or extensions type things. Current test data shows the following mapping:
                10 -  Image (JPEG)
                11 - Image (JPG)
                14 - Image (PNG)
                19 - Image (WEBP)
                53 - Image (HEIC)
                100 - Audio (MP3)  
                102 - Audio (M4A)
                107 - Audio (OPUS)             
                200 - Video (MP4)
                311 - Document (CSV)
                312 - Document (PDF)
                315 - Document (DOCX)
                330 - Document (TXT)
                400 - Archive (APK)
                410 - Archive (ZIP)
                411 - Archive (RAR)
                506 - (VCF)
                526 - (TORRENT)
                12289 - Folder
        
            This leads me to that it is something like:
                10 -99 = Images
                1xx = Audio
                2xx = Video
                3xx = Documents
                4xx = Archives
                5xx = Others
                12289 = Folder

Getting and interpreting the data

1. Get an Operations Overview

SELECT
mDate [Operation Date],
_id [Operation ID],
mOperationType [Operation Type],
mItemCount [# of Files],
mFolderCount [# of Folder],
mPageType [Page Type],
mOperationResult [Result]
FROM operation_history;

2. Get list of all operations and the corresponding files / folders.

SELECT
oh.mdate [Operation Date],
ohd.operation_id [Operation ID],
ohd.src_path [Source Path],
ohd.src_file_id [Source File ID],
ohd.dst_path [Destination Path],
ohd.dst_file_id [Destination File ID],
oh.mOperationType [Operation Type],
oh.mItemCount [# of Files],
oh.mFolderCount [# of Folders],
oh.mPageType [Page Type],
oh.mOperationResult [Result],
oh.mMemoryFullCapacity [Storage Capacity Info]
FROM operation_history_data ohd
JOIN operation_history oh ON oh._id = ohd.operation_id

3. Are there any parsers out there?

I also looked into existing tools for parsing this data. Currently, ALEAPP includes a parser for the File Operations History, but it only supports Android versions below 13 and analyzes only the operation_history table.

After reviewing the code, I concluded that it would be possible to adapt the parser to support newer Android versions as well. I plan to do this in the future, but for now, I want to focus on my analysis of Samsung apps without interrupting the workflow by refactoring an existing parser.

Meaning of the data / Conclusion

The entries in the File Operations History reflect the file operations performed by the Samsung My Files app. They provide a useful overview of what actions were taken on files and folders within the system.

The data is retained for a long period—in my test dataset, I was able to trace operations going back about one and a half years. I did not observe any triggers that would automatically delete entries from the database.


What the data don't show:

It is important to note that the database does not log individual files inside a folder when an operation is performed on the folder itself.

Example:

If I decide to move a folder to a new location, I select the folder in the UI and click “Move.” The File Operations History will store an entry for this folder and the move operation—but it will not create entries for each file inside the folder.

However, it may be possible to reconstruct some file-level operations by looking back at earlier entries. For example, if a file was created in that folder 30 minutes before the move and was not subsequently deleted based on entries in the database, you could infer that it was included in the move operation. But I would like to always double check this with additional data if possible in any way.

Additionally, the database only logs operations performed by Samsung apps, specifically the My Files app or calls to this app. Any operations done through third-party file managers will not appear in the File Operations History.

Future work:

I have stored my SQL queries for extracting data from the database in my GitHub repository for later use, such as building a parser:
https://github.com/kalink0/useful_scripts/blob/master/sql/Android/Samsung%20Apps/sMyFiles.sql

I also plan to create additional posts on Samsung apps, sharing my findings step by step.

Sunday, December 7, 2025

Samsung Core Services - Module "ai search" and what data it holds

Today I will share my result about an analysis I did on a Samsung device and especially the Samsung Core Services.

What does ChatGPT says about SCS?:

Samsung Core Services (SCS) is a system service on Samsung devices that provides essential background functionality for Samsung apps and One UI features. It supports services like search indexing, metadata and image processing, entity/phrase extraction, and suggestions, enabling apps and system features to work seamlessly.

Sounds interesting - so I took a look into the data.

Testing was done on a Samsung device with Android 16 installed.

The data of Samsung Core Services can be found at the (user) data folder under ../com.samsung.android.scs/

You can find the normally known app structure in the folder with e.g. subfolders "databases" and "files".

I took a look into the databases, but nothing interesting came up - doesn't look like any user generated or user dependent stuff is in it.

So next step I looked into the files-folder.

There are two subfolders.

1. zip -> empty - so nothing to look at

2. aisearch -> okay - ai + search - what could this be? and files/folder are in there.


aisearch

The following folders can be found in the folder aisearch:


bnlp -> could mean "Natural Language Processing" - B could stand for "Bayesian". My master studies are a bit far away (yeah - i am getting older :-D) - but in this context  it is possible.

There are two files in it. One is noun_list.txt which contains a list of words that can be found on an android device (see next pic).


I see whatsapp, telegram, instagram, chatgpt - yepp, these are some of the installed apps on the device. But, to be honest, not very useful i think at least at the moment.

I also took a look into the client, indexes and log folders. I see structures and some log files - what modules are running and when - also how many files were processed. This looks like data for text processing.

I found traces that Apache Lucene is used under the hood - now I am certain, that what I see has something to do with text indexing of files e.g. to give a user the possibility to search on the devices and also in the files on the device.

Okay, one folder left - raw_txt - what is in it? Some sample files perhaps?

Surprise - there are txt-files - the file names seem to lead to existing or formerly existing pdf-files on the device.


Now - that is interesting.

One example file name: 0_732749_CV Marco.pdf.txt

Pattern of the file names:

[uid]_[internal_file_id]_[file_name].pdf.txt

Where:

uid = the id of the user, 0 for main user, or e.g. 150 for secure folder - the origignal file is related to.

internal_file_id = I don't saw any trace where this id leads to - it seems like some internal id for the service - I double checked in the databases

file_name = the name of the file the moment it was indexed


But does the content of the files come from real files on the device? Let's see:



-> Yes - in this example  it contains the text of the pdf file. In the picture above it shows the start of the AGB (General Terms and Conditions - The fine print nobody reads but everyone agrees to—like the snooze button of contracts) of a German Provider - identical to the content of the original pdf.

I can also see traces of pdf files that are not on the device anymore. 

So it is possible to find data of deleted at least pdf files in this folder?! - nice.

The timestamp of the files seem to relate to there index time - it is close to the creation time (I know this at least for my cv) - but not exactly identical.

I don't have any information on when exactly the Samsung Core Service and its module ai search indexes a file but I know that the file must have been existed on the device the moment it was indexed. And the text content must have been in it - as based on the data I see on my test device.

Conclusion

The most interesting part for me are the files in the subfolder raw_txt. These files contain the textual content of pdf files on the test device - even for deleted ones.

The deletion of some files was about 2 weeks ago - but I didn't test for how long the data is stored in the raw_txt folder.

There is only the file name of the corresponding original file - at least I didn't find any info on the original file path or e.g. a hash values of the original file.

There is also only the creation date of the index file in the raw_txt folder - from that I could say that the original file must have existed on the device at the same time the index file was created  or at least at the moment the indexing was executed what should be close to the creation time of the index file - but not more.

There are some metadata available in the app context of the Samsung Core Services - I didn't go very deep into this stuff.

This was a really quick dive into the data - I did not any reversing on the exact functionality of the Samsung Core Services and ai search or perhaps any other modules in it. Also I did not take a deep look into the config file in the shared_prefs folder - it could be possible that service/module settings are stored there so we can see what data we could expect. As always - I will put this on my way too long to-do list. ;-) 

Thx for your time and have a nice day.


Saturday, January 11, 2025

Windows Recycle Bin - The known and the unknown

Moin! :-)

Today I write this post about an already really well known artifact of Windows Systems - the Recycle Bin.

Why? Because I had a few more specific questions about the behavior of the recycle bin. I looked for answers to these questions but was not able to find any with a quick search - so I decided to just test it myself.

This post will first give a short overview of the storing mechanism of the recycle bin, something like the well known basics.

After this, I will look into my questions. 

My questions were the following:

1. What does happen if the user restores a file?

2. What does happen if a user deletes the same file again after restoring?

3. What does happen if a file is deleted from PowerShell oder CMD?

4. Is there a difference between file systems?


I did the testing on a Windows 10 system. As far as I could see the behavior should by identical to Windows 11.


The basics

I will only give a short overview of the working without a deep look

As mentioned, I looked at Windows 10 or newer.

For this operating system the Recycle Bin stores two different files for deleted files:

1. The $R file - this file holds the data itself from the deleted file
2. The $I file - this file holds the corresponding meta data for the deleted file

The $I file holds data like the time and date of the deletion in UTC and the original file path and file name. Or, to describe it more correctly, the creation, last accessed and the last write timestamp of the $I file is the deletion timestamp of the original file.

If you have a file with the name "4n6.txt" and delete it, there will be two files in the Recycle Bin directory. One starting with $R, one with $I - and as suffix a 6 char long alphanumeric string. The extension is the same like the original file.

There is one Recycle Bin per partition in Windows. E.g. for drive C: it is c:\$Recycle.Bin

This means first there is an Recycle Bin on every partition.

Additionally, on NTFS file systems, the files in the recycle bin are stored under a folder that is named like the SID of the user who has deleted the file. I will show the difference to FAT32 later in this post. This post won't cover SIDs itself.

And - if the recycle bin is emptied or one specific file is deleted from the recycle bin both files, $I and $R are removed.

I used the tool RBCmd from Eric Zimmerman to do my research - you can find it at https://ericzimmerman.github.io/#!index.md

Okay, so let's start with the questions.

Restoring a file

What does happen if the user restores a file? I started with a complete empty Recycle Bin.

I deleted three files from my desktop and executed RBCmd with the following output:


We see in the output the three deleted files are referenced correctly.

Now I restore the files. And re-execute RBCmd with the following output:


It is the same - this is okay, because the tool parses the $I files. And these files are still there. But the $R files are gone.

I also restarted the system, but without any effect - the $I files are still there.

So, when restoring files, the $I files will stay. This means one can say that a file with a specific name, path and size was deleted in the past and than was restored.

Okay, second question.

Deletion of same file after restoring

What does happen if a user deletes the same file again after restoring?

I did a test on another drive with a clean Recycle Bin. First I deleted one file - restored it - deleted it again - RBCmd gives me the following:




As you can see, you have two $I files - different names - but same meta data - except for the deletion timestamp.

This means you can have more than one trace to the same file. For a file you only know the original timestamp, the file path, the file name and the file size. The content is only stored in the $R file.

Deletion from Terminal/CMD/Powershell

3. What does happen if a file is deleted via PowerShell or CMD?

When deletion is done from Terminal/Powershell/CMD there will not be any traces in the Recycle Bin. The behavior is similar to Linux - when not using the GUI the files will be deleted directly.

I also tested Double Commander as a different file manager and deleted a file from this app. For Double Commander the normal traces in the Recycle Bin still exist.

Different File Systems

So, what I did not mention yet - all testing was done with NTFS as the file system.

Is there a difference to FAT32?

I assumed that this is not the case because I thought the Recycle Bin is written by the Operation System and it is not important what the underlying file system is for the Recycle Bin - perhaps a bit naive.

So, assumptions need to get verified.

I created a FAT32 volume and created a few files and also deleted a few. There was one difference I could see:

On NTFS there was a folder per user in the Recycle Bin with the SID - and in this folder the files ($I and $R) are stored.

ON FAT32 the $I and $R  files are directly stored in the Recycle Bin folder. You do not have any information on the user who has deleted the file in the Recycle Bin. Please find the ouptut of RBCmd of a FAT32 Recycle Bin below:




Conclusion

I had a few specific question and could answer them.
I want to say that you always should use different artifacts to validate results. E.g. you could use the USN journal for validating the deletion of a file. Never trust only one artifact. Look at the whole picture - this post only shows the answers to the really specific questions!

Also, important to say - this post only discusses the behavior of the Recycle Bin - it is not about deletion of files and if they are recoverable or not!


I hope that you also learned a bit and enjoyed your read.




Tuesday, September 24, 2024

Withings HealthMate on iOS

Moin! :-)

In the year 2020 I did an analysis on the HealthMate App of Withings on Android devices.

I decided that it is time to do the same for the corresponding app on iOS devices.

For my last posts I always wrote a parse for ALEAPP - because they were about Android or Apps on Android. So this time I also wrote a parser for iLEAPP (Github Link)  - PR is created - should be merged soon.

In my experience there is always a lot of useful data stored in health apps. Data such like Activities (when, where, how intense), general movements, health status and and and...

My test device for this was an Apple iPhone 12 mini with iOS 17.5.1 installed. I used a Full File System Acquisition for my analysis.

The app is called: Withings Health Mate App (com.withings.wiScaleNG)

The app syncs the data from the devices to the Withings servers. I use the app and some of the Withings devices since 2019.

The Withings devices I use/used are the scale BodyComp and the watches ScanWatch, ScanWatch 2 and ScanWatch HR.

The data you can get out of the app is dependent on what data you track and what your devices can measure.


The following data can be found in general and are discussed in this post:

  1. Account info
  2. Messages (between users that are connected to each other)
  3. Devices connected to the account 
  4. Measurements
    • Automatic/Cyclic measurements made by the device (e.g. steps, heart rate, location, SPO2, temperature)    
  5. Tracking / Activities
    • Specific activities tracked manually or detected automatically (e.g.  Cycling, Swimming, Running)  

I only look at the data stored in the app. I won't take a look onto my Withings devices or into the data on the provider site.


Where is the data stored?

In the corresponding Sandbox Path of the App the interesting data is stored in the Folder "Library/Application Support" and its subfolders.

I will give the exact location in the sandbox path to every file in the corresponding section below.


Account Info

The used account of the app can be found in a JSON file.

Path: %SandboxPath%/Library/Application Support/
Name: account

You can get the following info out of the file:
  1. User ID
  2. First Name
  3. Last Name
  4. Short Name
  5. Birthdate (Stored as Apple Cocoa Core Data Timestamp - Local Time))
  6. E-Mail
  7. Creation Date (Stored as Unix Epoch Timestamp - UTC)
  8. Last Modified Date (Stored as Unix Epoch Timestamp - UTC)

Additionally there is stored info about the used security mechanisms (Password/biometric), the used auhtentication tokens and some other stuff.

Messages

In the app it is possible to write messages to other users. To do this the users need to be connected. Connected means in the app that they are competing against each other.
As far as I know there are no group chats possible at the moment.

The message data ist stored in a SQLITE database.

Path: %SandboxPath%/Library/Application Support/coredata
Name: [User ID]_HM3Timeline.sqlite

Table of interest: ZHMTIMELINEEVENT.

In the field ZTYPE the value gives info what type of message it is. Message from users have the value "HMTimelineMessageEvent".
System messages, e.g. if a measurement was above normal level, the value is "HMTimelineTextEvent".
I am interested in the user generated messages now, so I focus on the first value here.

The other interesting fields in the table are:


FieldMeaningAdditional info
ZUSERIDUser ID of the account in the app8-digit
ZSENDERIDUser ID of the sender of the message8-digit
ZRECEIVERIDUser ID of the receiver of the message8-digit
ZSENDERLASTNAMELast name of the sender
ZSENDERFIRSTNAMEFirst name of the sender
ZDATETimestamp of the message Apple Cocoa Core Data Timestamp
In Local Time
ZWSMODIFIEDDATELast modification date of the messageApple Cocoa Core Data Timestamp
In UTC
ZEXPIRATIONDATESet expriation date of the messageFunction not tested yet. In my data there were still messages in the database after the expiration date. Could be just relevant for the UI.
ZTYPEMESSAGEType of the messageFour values in my data:
- Cheer
- Taunt
- Custom
- Message
ZMESSAGE2Content of the message


Devices

Info to connected devices are stored in the following SQLITE database

Path: %SandboxPath%/Library/Application Support/coredata
Name: associated_devices.sqlite

Table of interest: ZWTDEVICE

Interesting fields:

FieldMeaningAdditional info
ZDEVICE_IDInternal Device ID8-digit
ZUSERIDUser ID of the sender of the message8-digit
ZCREATEDDate of the association of the device with the accountUnix Epoch Timestamp
In UTC
ZLASTCONNECTIONLast connection/sync with the deviceApple Cocoa Core Data Timestamp
In UTC
ZLAST_WEIGHINLast weigh in on the device - the last time the device got dataApple Cocoa Core Data Timestamp
In UTC
ZMACMAC address of the device
ZFIRMWAREFirmware version of the device at the last sync
ZLATITUDELatitude value of last syncNot too precise - dependent on the device and type of sync (via BT to App or via W-LAN)
ZLONGITUDELongitude value of last syncNot too precise - dependent on the device and type of sync (via BT to App or via W-LAN)
ZTIMEZONE

Timezone set on the device

Format: "Europe/Berlin"

ZISSYNCDISABLED

0 = Sync enabled
1 = Sync disabled




Measurements

I use the term measurement for the values that are captured periodically and automatically by the app.


Path: %SandboxPath%/Library/Application Support/coredata
Name: [User_ID]_vasistas.sqlite

Table of interest: ZVASISTAS

In the table the field ZCATEGORY stores info about the category of the data. Dependent on the value in this field different other fields are filled with the data. 
Please understand, that the values in ZCATEGORY are the ones in my data. It is possible, that there exist other values in the field ZCATEGORY, if other measurements are taken from other devices.


Overview of the interesting fields:

FieldMeaningAdditional info
ZCATEGORYCategory of the data measured:
0 = Steps
2 = Heart rate
3 = ??
5 = Location
6 = SPO2
8 = ??
12 = Body temperature
For the values 3 and 8 I, at the moment, don't have any idea what they mean.

ZDEVICEIDDevice ID of the device that measured the dataCan be NULL if the device was the phone itself (e.g. data from Apple Health or from the HealthMate app -> GPS)
ZDURATIONDuration of the measurement Duration is in seconds
ZTIMESTAMPStart Time of the measurementApple Cocoa Core Data Timestamp
In UTC
ZSTEPS# of steps recordedOnly filled for category 0 - Steps
ZDISTANCEDistance recordedOnly filled for category 0 - Steps
The distance is calculated by the app - based on the size of the person and the # of steps
ZCALORIESEARNEDAdditional calories earnedOnly filled for category 0 - Steps
This value is calculated by the app based e.g. on the size and the body composition of the user
ZHEARTRATE1Measured heart rateOnly filled for category 2 - Heart rate
ZLATITUDELatitude valueOnly filled for category 5 - Location
As decimal value
ZLONGITUDE

Longitude value

Only filled for category 5 - Location
As decimal value
ZALTITUDE

Altitude Value

Only filled for category 5 - Location
In meters
ZDIRECTION

Direction the device is going to

Only filled for category 5 - Location
In degree (0 - 359)
ZRADIUS

Radius around the coordinates - Means the uncertainty
Only filled for category 5 - Location
In meters
ZSPEED

Speed of the device

Only filled for category 5 - Location
In miles per hour (mph)
ZSPO2

Quality of the SPO2 value

Only filled for category 6 - SPO2
Value is in percent
ZASCENT1

Not known yetOnly filled for category 8 - Unknown
ZTEMPERATURE

Body temperature

Only filled for category 12 - Temperature
In degree Celsius


Tracking / Activities

The last thing I looked at were the activities tracked by my devices.
The activities are tracked in different cases:
  1. When I explicitly start tracking on one of my devices. e.g. when I go for a 5k run I use my watch and my phone connected to each other for tracking. - I can decide which type of activity is tracked in this case.
  2. When the device, mostly the watch in my case, recognize an activity - such as when I go by bike to my work place my watch recognizes this automatically. - What is detected works mostly fine on my side - but I had cases where something wrong was detected. So we need to keep this in mind when looking at the data. Sleeping is tracked the same way
Summary data of a day (24-hour timespan) is tracked (or better caluclated) for statistics and stored in the same database. Consist of e.g. total # of steps, spent time in heart rate zones, in/active minutes of the day.

Good to know: It is possible to delete tracked activities/sleep in the app. We will take a look at what this means for the data.

Path: %SandboxPath%/Library/Application Support/coredata
Name: [User_ID]_Tracks.sqlite

Tables of interest: ZTRACK
Overview of the interesting fields:

FieldMeaningAdditional info
ZDEVICEIDDevice ID of the source device

ZSUBCATEGORYID of the Subcategory - e.g.:
4 = Walking
16 = Others
18 = Running
22 = Cycling
The names of the subcategory can be joined from the table ZACTIVITYSUBCATEGORY from the same database
ZSTARTDATEStart time of the trackApple Cocoa Core Data Timestamp
In UTC
ZENDDATEEnd time of the trackApple Cocoa Core Data Timestamp
In UTC
ZREFERENCEDATEThe day the tracked data is referenced to.Apple Cocoa Core Data Timestamp
In UTC
ZMODIFIEDDATEDate of last modificationApple Cocoa Core Data Timestamp
In UTC
Also the app itself seems to modify anything - the timestamp is updated than. Almost all my Modified timestamps are younger than my created but I did not modify anything.
ZMANUALSTARTDATEStart time for manual tracking started e.g. on a watch Apple Cocoa Core Data Timestamp
In UTC
ZMANUALENDDATEEnd time for manual trackingApple Cocoa Core Data Timestamp
In UTC
ZSTEPSNumber of steps
ZCALORIESEARNED

Additional calories earned

ZISREMOVED

1 = Removed by user
0 = Default - Not removed

For my data I have entries that are set to 1 in the database. This means: Removed tracks are still in the database!
But these tracks are not shown in the UI anymore.
ZPAUSEDURATION

Pause in the tracking

In seconds
Only for manual tracking
ZNOTE

Added notes to the tracking by the user

ZTIMEZONE
Timezone where the device was in when tracking started.


ZCITY

Located city where the tracking was started

Only used when manual tracking is started

There a lot of other fields in there and additionally to this data one should take look into the table ZTRACKEXTENSION where specific data to the tracks can be stored.

Because of the amount of different types of data and fields stored in this database I decided to create SQL-queries for different result types

1. Tracked sleep
2. Tracked activities (manual and automatic)
3. Summary of the day


Tracked sleep

In the data to recognize sleep the following field values should be checked to identify the entries:

ZSUBCATEGORY IS NULL
ZTYPE = 36

My build SQL-Query with the relevant fields is than something like:
  SELECT  
  ZDEVICEID,
  DATETIME('2001-01-01', "ZSTARTDATE" || ' seconds') [STARTDATE],
  DATETIME('2001-01-01', "ZENDDATE" || ' seconds') [ENDDATE],
  DATETIME('2001-01-01', "ZREFERENCEDATE" || ' seconds') [REFERENCEDATE],
  DATETIME('2001-01-01', "ZMODIFIEDDATE" || ' seconds') [MODIFIEDDATE],
  DATETIME('2001-01-01', "ZMANUALSTARTDATE" || ' seconds') [MANUALSTARTDATE],
  DATETIME('2001-01-01', "ZMANUALENDDATE" || ' seconds') [MANUALENDDATE],
  ZLIGHTSLEEPDURATION,  
  ZREMSLEEPDURATION,  
  ZDEEPSLEEPDURATION,  
  ZDURATIONTOSLEEP,  
  ZTIMETOGETUP,  
  ZWAKEUPCOUNT,  
  ZWAKEUPDURATION  
  FROM ZTRACK  
  WHERE ZSUBCATEGORY IS NULL AND ZTYPE = 36

With this data you have the information, when and how the user slept.

Summary of the day

For the summary of a day the following fields should be checked to identify the entries:

ZTRACKID IS NULL
DEVICEID IS NULL

My build SQL-Query with the relevant fields is than something like:
   
  SELECT  
  DATETIME('2001-01-01', "ZSTARTDATE" || ' seconds') [STARTDATE],
  DATETIME('2001-01-01', "ZENDDATE" || ' seconds') [ENDDATE],
  DATETIME('2001-01-01', "ZREFERENCEDATE" || ' seconds') [REFERENCEDATE],
  DATETIME('2001-01-01', "ZMODIFIEDDATE" || ' seconds') [MODIFIEDDATE],
  DATETIME('2001-01-01', "ZMANUALSTARTDATE" || ' seconds') [MANUALSTARTDATE],
  DATETIME('2001-01-01', "ZMANUALENDDATE" || ' seconds') [MANUALENDDATE],
  ZDURATIONINACTIVE,  
  ZDURATIONINTENSE,  
  ZDURATIONMODERATE,  
  ZDURATIONSOFT,  
  ZSTEPS1,  
  ZDISTANCE1,  
  ZTIMEZONE
  FROM ZTRACK  
  WHERE ZTRACKID IS NULL AND ZDEVICEID IS NULL


With this you can get an overview how active the user was on the day - more details for a day can be get out of the measurements and the tracked activities.

Tracked Activities

The tracked activities are built together from three tables from the database

ZTRACK - for the main data
ZACTIVITYSUBCATEGORY - for the type of the activity
ZTRACKEXTENSION - for additional data to a track
And ZSTEPS never seems to be empty (in my data)


My build SQL-Query with the relevant fields is than something like:

  SELECT
  t.ZDEVICEID,
  sc.ZNAME,
  t.ZISREMOVED,
  t.ZPAUSEDURATION,
  DATETIME('2001-01-01', "ZSTARTDATE" || ' seconds') [STARTDATE],
  DATETIME('2001-01-01', "ZENDDATE" || ' seconds') [ENDDATE],
  DATETIME('2001-01-01', "ZREFERENCEDATE" || ' seconds') [REFERENCEDATE],
  DATETIME('2001-01-01', "ZMODIFIEDDATE" || ' seconds') [MODIFIEDDATE],
  DATETIME('2001-01-01', "ZMANUALSTARTDATE" || ' seconds') [MANUALSTARTDATE],
  DATETIME('2001-01-01', "ZMANUALENDDATE" || ' seconds') [MANUALENDDATE],
  te.ZINTENSEDURATION,  
  te.ZMODERATEDURATION,  
  te.ZLIGHTDURATION,  
  te.ZMIN,
  te.ZMAX,
  te.ZAVG,
  t.ZSTEPS,
  t.ZDISTANCE,  
  te.ZMINSPEED,  
  te.ZAVERAGESPEED,  
  te.ZMAXSPEED,  
  te.ZDISTANCE,  
  te.ZSTARTCOORDINATELATITUDE,  
  te.ZSTARTCOORDINATELONGITUDE,  
  te.ZENDCOORDINATELATITUDE,  
  te.ZENDCOORDINATELONGITUDE,  
  te.ZREGIONCENTERLATITUDE,  
  te.ZREGIONCENTERLONGITUDE,  
  te.ZMINTEMPERATURE,  
  te.ZAVGTEMPERATURE,  
  te.ZMAXTEMPERATURE,
  t.ZTIMEZONE
  FROM ZTRACK t
  INNER JOIN ZACTIVITYSUBCATEGORY sc ON t.ZSUBCATEGORY = sc.Z_PK
  INNER JOIN ZTRACKEXTENSION te ON t.Z_PK = te.ZTRACK
  WHERE t.ZSTEPS IS NOT NULL

There are quite a lot fields that are interesting. I recommend to filter for what you need.

Some things to know about the fields:

We have to fields with the label "ZDISTANCE".

The one from the table ZTRACK is the distance calculated without GPS.
The one from the table ZTRACKEXTENSION is measured via the GPS of the phone.
It depends on the tracked activity what type is used.


Conclusion and further work

Puh, lot of data in there. This was just a first view on the data and some extraction of them.
The data is stored a bit differently to how it is stored on Android - so I could not just copy and paste things ;-)

Analysis was fun. And I am not finished with the work yet.

Why? 
1. Well some of the data I looked for, I could not find - 
For example:
- The detailed GPS data for a track - not just the start, center and end coordinates

2. After I did the acquisition of the data I connected Withings with Apple Health - I want to take a look what effect this has on the data - and also how does the Apple health data looks than.

3. My SQL-Queries are not fully finalized. I want to make them more versatile.

4. Some thoughts on visualization - at the moment just tables - but diagrams and maps would be fine.


I scripted different parsers for the Withings Health Mate App artifacts to be included in iLEAPP. I think it is important to give back and it is also a nice training for me.


Health Apps always store very interesting data. Data that can help to determine what a user did at a specific time. But, just like always - never look only on the data of one app or one type. Always try to correlate data and see if different data (types) lead to the same result.

Please - if you use my queries - double check everything. They should help to get a first view on the data. But look for yourself in the database to verify. Especially the query for the Tracked activities was tricky.


I am just happy that I had a bit of time to look into the app also on iOS :-)

Hope you had a nice read.