essaouira

Android's Enterprise APIs related to device administration offer many interesting features.

With a device owner app, you are able to perform many privileged tasks that are normally not available to regular apps. You can lock your app to the screen to create a kiosk app, update your app without user interaction, or even perform a device reboot.

Android 7 offers some new interesting features that allow you to monitor various information related to device's health.

I played a bit with this feature and in this post I'll show a quick guide on how to use it and what experience I had.

Make Your App a Device Owner

I showed how to create and activate a device owner app in my previous post. Therefore, the steps in this section will only be a quick summarization.

This step is necessary before you'll be able to use any of the functionality in the following sections.

You can start by implementing a DeviceAdminReceiver

class DevAdminReceiver: DeviceAdminReceiver() {
    override fun onEnabled(context: Context?, intent: Intent?) {
        super.onEnabled(context, intent)
        Log.d(TAG, "Device Owner Enabled")
    }
}

Create device_admin.xml resource file inside of res/xml with metadata that contains information related to device administration

<?xml version="1.0" encoding="utf-8"?>
<device-admin xmlns:android="http://schemas.android.com/apk/res/android">
    <uses-policies>
    </uses-policies>
</device-admin>

Declare your DevAdminReceiver component inside of AndroidManifest.xml

<application
        android:testOnly="true"

        ...>
    ...
    <receiver
        android:name="eu.sisik.kioskbrowser.DevAdminReceiver"
        android:label="@string/app_name"
        android:permission="android.permission.BIND_DEVICE_ADMIN" >
        <intent-filter>
            <action android:name="android.app.action.DEVICE_ADMIN_ENABLED" />
        </intent-filter>

        <meta-data
            android:name="android.app.device_admin"
            android:resource="@xml/device_admin" />
    </receiver>
...
</application>

Please note that I also added the testOnly flag to the <application> tag. If you are enabling device owner via ADB, this flag is necessary since Android 7.0.

Once you're app is complete and installed on the device, you can activate it as device owner via ADB by executing the following shell command

adb shell dpm set-device-owner eu.sisik.kioskbrowser/.DevAdminReceiver

This command will only succeed when there are no other accounts configured on the device. So ideally you execute this right after the first boot or after a fresh factory reset.

Measuring Temperature

The main class that gives you access to device monitoring features is the HardwarePropertiesManager.

Executing methods from HardwarePropertiesManager class will thrown a SecurityException, if you didn't configure your app as a device owner.

Before calling any methods, you can first try to check if your app is a device owner app

val dpm = getSystemService(Context.DEVICE_POLICY_SERVICE) as DevicePolicyManager

if (dpm.isDeviceOwnerApp(packageName)) {
    // Great, we are device owner. We can call HardwarePropertiesManager methods
    // ...
}

To measure the temperature, you first get an instance of the HardwarePropertiesManager system service and call getDeviceTemperatures()

val hpm = getSystemService(HardwarePropertiesManager::class.java)
val temperatures = hpm.getDeviceTemperatures(DEVICE_TEMPERATURE_CPU,
    TEMPERATURE_CURRENT)

for (temperature in temperatures)
    Log.d(TAG, "temperature Celsius = " +  temperature)

This can give you the temperature of parts like CPU, GPU, or Battery. The returned array can also be empty if the device doesn't provide these values (which was the case on all of the devices that I've played with).

Measuring CPU Usage

The getCpuUsages() gives you CpuUsageInfo. This will allow you to get the number of milliseconds since system boot - either total time which includes idle CPU time, or only the active time.

It should return null for each offline core

val dpm = getSystemService(Context.DEVICE_POLICY_SERVICE) as DevicePolicyManager
for (i in 0 until hpm.cpuUsages.size) {
    val usageInfo = hpm.cpuUsages.getOrNull(i)
    if (usageInfo != null) {
        Log.d(TAG, "Minutes since last boot " + (usageInfo!!.active / 1000 / 60))
        Log.d(TAG, "Minutes since last boot (including idle CPU) " 
                + (usageInfo!!.total / 1000 / 60) + " minutes")
    }
}

Luckily, I was able to get some values on my Nokia 6.

Fan Speed

getFanSpeeds() returns the speed in RPM, but I again didn't have any device that would actually support this

val dpm = getSystemService(Context.DEVICE_POLICY_SERVICE) as DevicePolicyManager

for (speed in  hpm.fanSpeeds)
    Log.d(TAG, "speed RPM = " +  speed)

Previous Post

Add a comment