Home | History | Annotate | Download | only in jni
      1 /*
      2  * Copyright (C) 2009 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 #define LOG_TAG "LightsService"
     18 
     19 #include "jni.h"
     20 #include <nativehelper/JNIHelp.h>
     21 #include "android_runtime/AndroidRuntime.h"
     22 
     23 #include <android/hardware/light/2.0/ILight.h>
     24 #include <android/hardware/light/2.0/types.h>
     25 #include <android-base/chrono_utils.h>
     26 #include <utils/misc.h>
     27 #include <utils/Log.h>
     28 #include <map>
     29 #include <stdio.h>
     30 
     31 namespace android {
     32 
     33 using Brightness = ::android::hardware::light::V2_0::Brightness;
     34 using Flash      = ::android::hardware::light::V2_0::Flash;
     35 using ILight     = ::android::hardware::light::V2_0::ILight;
     36 using LightState = ::android::hardware::light::V2_0::LightState;
     37 using Status     = ::android::hardware::light::V2_0::Status;
     38 using Type       = ::android::hardware::light::V2_0::Type;
     39 template<typename T>
     40 using Return     = ::android::hardware::Return<T>;
     41 
     42 class LightHal {
     43 private:
     44     static sp<ILight> sLight;
     45     static bool sLightInit;
     46 
     47     LightHal() {}
     48 
     49 public:
     50     static void disassociate() {
     51         sLightInit = false;
     52         sLight = nullptr;
     53     }
     54 
     55     static sp<ILight> associate() {
     56         if ((sLight == nullptr && !sLightInit) ||
     57                 (sLight != nullptr && !sLight->ping().isOk())) {
     58             // will return the hal if it exists the first time.
     59             sLight = ILight::getService();
     60             sLightInit = true;
     61 
     62             if (sLight == nullptr) {
     63                 ALOGE("Unable to get ILight interface.");
     64             }
     65         }
     66 
     67         return sLight;
     68     }
     69 };
     70 
     71 sp<ILight> LightHal::sLight = nullptr;
     72 bool LightHal::sLightInit = false;
     73 
     74 static bool validate(jint light, jint flash, jint brightness) {
     75     bool valid = true;
     76 
     77     if (light < 0 || light >= static_cast<jint>(Type::COUNT)) {
     78         ALOGE("Invalid light parameter %d.", light);
     79         valid = false;
     80     }
     81 
     82     if (flash != static_cast<jint>(Flash::NONE) &&
     83         flash != static_cast<jint>(Flash::TIMED) &&
     84         flash != static_cast<jint>(Flash::HARDWARE)) {
     85         ALOGE("Invalid flash parameter %d.", flash);
     86         valid = false;
     87     }
     88 
     89     if (brightness != static_cast<jint>(Brightness::USER) &&
     90         brightness != static_cast<jint>(Brightness::SENSOR) &&
     91         brightness != static_cast<jint>(Brightness::LOW_PERSISTENCE)) {
     92         ALOGE("Invalid brightness parameter %d.", brightness);
     93         valid = false;
     94     }
     95 
     96     if (brightness == static_cast<jint>(Brightness::LOW_PERSISTENCE) &&
     97         light != static_cast<jint>(Type::BACKLIGHT)) {
     98         ALOGE("Cannot set low-persistence mode for non-backlight device.");
     99         valid = false;
    100     }
    101 
    102     return valid;
    103 }
    104 
    105 static LightState constructState(
    106         jint colorARGB,
    107         jint flashMode,
    108         jint onMS,
    109         jint offMS,
    110         jint brightnessMode){
    111     Flash flash = static_cast<Flash>(flashMode);
    112     Brightness brightness = static_cast<Brightness>(brightnessMode);
    113 
    114     LightState state{};
    115 
    116     if (brightness == Brightness::LOW_PERSISTENCE) {
    117         state.flashMode = Flash::NONE;
    118     } else {
    119         // Only set non-brightness settings when not in low-persistence mode
    120         state.flashMode = flash;
    121         state.flashOnMs = onMS;
    122         state.flashOffMs = offMS;
    123     }
    124 
    125     state.color = colorARGB;
    126     state.brightnessMode = brightness;
    127 
    128     return state;
    129 }
    130 
    131 static void processReturn(
    132         const Return<Status> &ret,
    133         Type type,
    134         const LightState &state) {
    135     if (!ret.isOk()) {
    136         ALOGE("Failed to issue set light command.");
    137         LightHal::disassociate();
    138         return;
    139     }
    140 
    141     switch (static_cast<Status>(ret)) {
    142         case Status::SUCCESS:
    143             break;
    144         case Status::LIGHT_NOT_SUPPORTED:
    145             ALOGE("Light requested not available on this device. %d", type);
    146             break;
    147         case Status::BRIGHTNESS_NOT_SUPPORTED:
    148             ALOGE("Brightness parameter not supported on this device: %d",
    149                 state.brightnessMode);
    150             break;
    151         case Status::UNKNOWN:
    152         default:
    153             ALOGE("Unknown error setting light.");
    154     }
    155 }
    156 
    157 static void setLight_native(
    158         JNIEnv* /* env */,
    159         jobject /* clazz */,
    160         jint light,
    161         jint colorARGB,
    162         jint flashMode,
    163         jint onMS,
    164         jint offMS,
    165         jint brightnessMode) {
    166 
    167     if (!validate(light, flashMode, brightnessMode)) {
    168         return;
    169     }
    170 
    171     sp<ILight> hal = LightHal::associate();
    172 
    173     if (hal == nullptr) {
    174         return;
    175     }
    176 
    177     Type type = static_cast<Type>(light);
    178     LightState state = constructState(
    179         colorARGB, flashMode, onMS, offMS, brightnessMode);
    180 
    181     {
    182         android::base::Timer t;
    183         Return<Status> ret = hal->setLight(type, state);
    184         processReturn(ret, type, state);
    185         if (t.duration() > 50ms) ALOGD("Excessive delay setting light");
    186     }
    187 }
    188 
    189 static const JNINativeMethod method_table[] = {
    190     { "setLight_native", "(IIIIII)V", (void*)setLight_native },
    191 };
    192 
    193 int register_android_server_LightsService(JNIEnv *env) {
    194     return jniRegisterNativeMethods(env, "com/android/server/lights/LightsService",
    195             method_table, NELEM(method_table));
    196 }
    197 
    198 };
    199