Managing lights in Android 12
Tags: android, kotlin
Published: 2021-04-27 15:42:21

The final release of Android 12 is still months away, but the developer previews are packed with interesting new apis. Some of them have already been officially introduced, others not yet. In this piece I will focus on one of the latter ones, package `android.hardware.lights` (which is present since dp3). Browsing through the api difference report I stumbled upon `android.hardware.lights.Light`. The docs currently say:

> Represents a logical light on the device.

We have four constants

1. `LIGHT_TYPE_INPUT_PLAYER_ID`
2. `LIGHT_TYPE_INPUT_RGB`
3. `LIGHT_TYPE_INPUT_SINGLE`
4. `LIGHT_TYPE_MICROPHONE`

and a bunch of query methods, for example `getId()` (returns the id of the light), `getName()` (the name of the light) and  `getType()`.

So, where do we get instances from? The usual suspect on Android is a manager obtained from `getSystemService()`. 

Let's take a look...

`android.hardware.lights.LightsManager`

> class allows control over device lights

We have three methods, `getLightState(Light light)`, `getLights()` and `openSession()`.

We can wire things up like this:

```kotlin
getSystemService(LightsManager::class.java)?.run {
  lights.forEach { light ->
    println("name: ${light.name}")
    val state = getLightState(light)
    print("color: ${state.color.toString(6)}")
  }
}
```

The state returned by `getLightState()` is an instance of `android.hardware.lights.LightState`. 

The docs say:

> Represents the state of a device light.
> 
> Controlling the color and brightness of a light is done
> on a best-effort basis. Each of the R, G and B channels
> represent the intensities of the respective part of an RGB
> LED, if that is supported. For devices that only support on
> or off lights, everything that's not off will turn the
> light on. If the light is monochrome and only the
> brightness can be controlled, the RGB color will be
> converted to only a brightness value and that will be used
> for the light's single channel.

Sounds like cool stuff. 😎

My example uses `getColor()`. The method returns

> the color and intensity associated with this LightState

If I run this code without further preparations, I get a `SecurityException`. 

![A LogCat snippet](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/74c5xzk0tbr8uwvstrgv.jpg)


We need to add a `android.permission.CONTROL_DEVICE_LIGHTS` to the manifest. Trouble is... It's not there yet.

![Screenshot showing a portion of the docs](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/11u3qgvddc31vvupyxo1.jpg)

In an attempt of not giving up too early I tried passing the string to the manifest nontheless:

```xml
<uses-permission android:name="android.permission.CONTROL_DEVICE_LIGHTS" />
```

Still got the exception. Hm. Maybe it's a dangerous permission...?

```kotlin
val requestPermissionLauncher =
  registerForActivityResult(
    ActivityResultContracts.RequestPermission()
  ) { isGranted: Boolean ->
    if (isGranted) {
      doIt()
    }
  }
when {
  ContextCompat.checkSelfPermission(
    this,
    "android.permission.CONTROL_DEVICE_LIGHTS"
  ) == PackageManager.PERMISSION_GRANTED -> {
    doIt()
  }
  else -> {
    requestPermissionLauncher.launch(
      "android.permission.CONTROL_DEVICE_LIGHTS"
    )
  }
}
```

Did not make a difference, either.

So, for now I just assume that I am either doing something wrong, or some things still need to be added. In any case, looking forward very much to get the new feature, as it sounds like fun. Especially changing lights and using sessions seems nice. Will be interesting to see if this will be doable in the emulator, too. 😎

Do you like such early investigations? Please share your thoughts in the comments.