Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added onyx note air3c #471

Closed
wants to merge 2 commits into from
Closed

Conversation

Gonlo2
Copy link

@Gonlo2 Gonlo2 commented Feb 27, 2024

Changes to support the onyx air book3c device. I have not been able to check that the code works after compiling it since I don't have the android development kit installed although I have checked that the paths to get/modify the white/warm light work correctly with the adb shell.

The android version is 12, the device version is 2023-12-29_16-55_3.5_f54c71ad2 and the device info is

Manufacturer: qualcomm
Brand: onyx
Model: noteair3c
Device: noteair3c
Product: noteair3c
Hardware: qcom
Platform: bengal

The log obtained after the execution of the compability test could be found in test.log.zip


This change is Reviewable

Changes to support the onyx air book3c device.

Device info:
Manufacturer: qualcomm
Brand: onyx
Model: noteair3c
Device: noteair3c
Product: noteair3c
Hardware: qcom
Platform: bengal
@pazos
Copy link
Member

pazos commented Feb 27, 2024

Thanks, looks good!

I have not been able to check that the code works after compiling it since I don't have the android development kit installed although I have checked that the paths to get/modify the white/warm light work correctly with the adb shell.

I'm afraid we cannot merge it without tests. We cannot trust adb

(whoops, button!)

@pazos pazos closed this Feb 27, 2024
@pazos pazos reopened this Feb 27, 2024
@pazos
Copy link
Member

pazos commented Feb 27, 2024

Building KO is easy, just a few steps: https://github.com/koreader/koreader/blob/master/doc/Building.md

If you don't want to bother with the task, let us know, so someone can create an APK for you to try :)

@Gonlo2
Copy link
Author

Gonlo2 commented Feb 29, 2024

I have compiled the application in debug mode but it seems that it gives permissions problems when trying to modify the brightness value preventing the app to start, then when I have time I will investigate to see if I can modify the brightness using the sdk with reflection.

@Gonlo2
Copy link
Author

Gonlo2 commented Mar 1, 2024

After investigating the SDK a little bit it seems that the light management works with this, during the next few days I will be using koreader on the device in case I see something weird, but it looks good. Wait until I used it a little before integrating it.

@Gonlo2 Gonlo2 force-pushed the add-onyx-note-air3c branch from 80c0524 to 84504d1 Compare March 1, 2024 18:11
@hugleo
Copy link
Contributor

hugleo commented Mar 2, 2024

Hi,

Can you test your device with this driver? https://github.com/koreader/android-luajit-launcher/blob/master/app/src/main/java/org/koreader/launcher/device/lights/OnyxAdbLightsController.kt

The code looks essentially the same.

How to enable the permission: https://github.com/koreader/koreader/wiki/Android-tips-and-tricks#adb-stuff

Reflection alone or double reflection (Android 10) will not work for these methods anymore. It works on the Onyx SDK because it utilizes the external library 'lsposed' to bypass the hidden API restrictions in Android >=11 ;-)
onyx-intl/OnyxAndroidDemo@377c243

@hugleo
Copy link
Contributor

hugleo commented Mar 3, 2024

I'm attempting to make OnyxSdkLightsController.kt generic. I assume that setLightValue and getLightValue will work properly for any Onyx device, which makes the driver more compact. Of course, we can still use the old methods setWarmLightDeviceValue, setColdLightDeviceValue, and getBrightnessConfig with slight adaptations ;-)

package org.koreader.launcher.device.lights

import android.app.Activity
import android.util.Log
import org.koreader.launcher.device.LightsInterface
import android.content.Context
import java.lang.Class.forName
import java.lang.reflect.Method

class OnyxAdbLightsController : LightsInterface {
    companion object {
        private const val TAG = "Lights"
        private const val MIN = 0
    }

    override fun getPlatform(): String {
        return "onyx-adb-lights"
    }

    override fun hasFallback(): Boolean {
        return false
    }

    override fun hasWarmth(): Boolean {
        return true
    }

    override fun needsPermission(): Boolean {
        return false
    }

    override fun getBrightness(activity: Activity): Int {
        return FrontLightAdb.getBrightness(activity)
    }

    override fun getWarmth(activity: Activity): Int {
        return FrontLightAdb.getWarmth(activity)
    }

    override fun setBrightness(activity: Activity, brightness: Int) {
        if (brightness < MIN || brightness > getMaxBrightness()) {
            Log.w(TAG, "brightness value of of range: $brightness")
            return
        }
        Log.v(TAG, "Setting brightness to $brightness")
        FrontLightAdb.setBrightness(brightness, activity)
    }

    override fun setWarmth(activity: Activity, warmth: Int) {
        if (warmth < MIN || warmth > getMaxWarmth()) {
            Log.w(TAG, "warmth value of of range: $warmth")
            return
        }
        Log.v(TAG, "Setting warmth to $warmth")
        FrontLightAdb.setWarmth(warmth, activity)
    }

    override fun getMinWarmth(): Int {
        return MIN
    }

    override fun getMaxWarmth(): Int {
        return FrontLightAdb.getMaxWarmth()
    }

    override fun getMinBrightness(): Int {
        return MIN
    }

    override fun getMaxBrightness(): Int {
        return FrontLightAdb.getMaxBrightness()
    }

    override fun enableFrontlightSwitch(activity: Activity): Int {
        return 1
    }

    override fun hasStandaloneWarmth(): Boolean {
        return false
    }
}

object FrontLightAdb {
    private const val TAG = "Lights"

    private val flController: Class<*>? = try {
        forName("android.onyx.hardware.DeviceController")
    } catch (e: Exception) {
        Log.w(TAG, "$e")
        null
    }

    private fun getMethod(name: String, vararg parameterTypes: Class<*>): Method? {
        return try {
            flController?.getMethod(name, *parameterTypes)
        } catch (e: Exception) {
            Log.w(TAG, "$e")
            null
        }
    }

    private val setLightValueMethod: Method? = getMethod("setLightValue", Integer.TYPE, Integer.TYPE)
    private val getLightValueMethod: Method? = getMethod("getLightValue", Integer.TYPE)
    private val getMaxLightValueMethod: Method? = getMethod("getMaxLightValue", Integer.TYPE)
    private val checkCTMMethod: Method? = getMethod("checkCTM")

    private fun getMaxLightValue(lightType: Int): Int {
        return try {
            getMaxLightValueMethod?.invoke(flController, lightType) as? Int ?: 0
        } catch (e: Exception) {
            Log.e(TAG, "Error getting the max light", e)
            0
        }
    }

    fun checkType(): Int {
        if (checkCTMMethod?.invoke(flController) as? Boolean == true) {
            return 1
        } else {
            return 0
        }
    }

    private val type = checkType()

    fun getBrightnessType(): Int {
        if (type == 1) {
            return 7
        } else {
            return 3
        }
    }

    fun getWarmthType(): Int {
        if (type == 1) {
            return 6
        } else {
            return 2
        }
    }

    private var brightnessType = getBrightnessType()
    private var warmthType = getWarmthType()
    private val brightnessMax = getMaxLightValue(brightnessType)
    private val warmthMax = getMaxLightValue(warmthType)

    fun getMaxBrightness(): Int {
        return brightnessMax
    }

    fun getMaxWarmth(): Int {
        return warmthMax
    }

    private fun getValue(method: Method?, lightType: Int): Int {
        return try {
            method?.invoke(flController, lightType) as? Int ?: 0
        } catch (e: Exception) {
            Log.e(TAG, "Error getting light value", e)
            0
        }
    }

    private fun setValue(method: Method?, lightType: Int, value: Int) {
        try {
            method?.invoke(flController, lightType, value)
        } catch (e: Exception) {
            Log.e(TAG, "Error setting light value", e)
        }
    }

    fun getWarmth(context: Context?): Int {
        return getValue(getLightValueMethod, warmthType)
    }

    fun getBrightness(context: Context?): Int {
        return getValue(getLightValueMethod, brightnessType)
    }

    fun setWarmth(value: Int, context: Context?) {
        setValue(setLightValueMethod, warmthType, value)
    }

    fun setBrightness(value: Int, context: Context?) {
        setValue(setLightValueMethod, brightnessType, value)
    }
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants