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 "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 <utils/misc.h> 26#include <utils/Log.h> 27#include <map> 28#include <stdio.h> 29 30namespace android { 31 32using Brightness = ::android::hardware::light::V2_0::Brightness; 33using Flash = ::android::hardware::light::V2_0::Flash; 34using ILight = ::android::hardware::light::V2_0::ILight; 35using LightState = ::android::hardware::light::V2_0::LightState; 36using Status = ::android::hardware::light::V2_0::Status; 37using Type = ::android::hardware::light::V2_0::Type; 38template<typename T> 39using Return = ::android::hardware::Return<T>; 40 41class LightHal { 42private: 43 static sp<ILight> sLight; 44 static bool sLightInit; 45 46 LightHal() {} 47 48public: 49 static void disassociate() { 50 sLightInit = false; 51 sLight = nullptr; 52 } 53 54 static sp<ILight> associate() { 55 if ((sLight == nullptr && !sLightInit) || 56 (sLight != nullptr && !sLight->ping().isOk())) { 57 // will return the hal if it exists the first time. 58 sLight = ILight::getService(); 59 sLightInit = true; 60 61 if (sLight == nullptr) { 62 ALOGE("Unable to get ILight interface."); 63 } 64 } 65 66 return sLight; 67 } 68}; 69 70sp<ILight> LightHal::sLight = nullptr; 71bool LightHal::sLightInit = false; 72 73static bool validate(jint light, jint flash, jint brightness) { 74 bool valid = true; 75 76 if (light < 0 || light >= static_cast<jint>(Type::COUNT)) { 77 ALOGE("Invalid light parameter %d.", light); 78 valid = false; 79 } 80 81 if (flash != static_cast<jint>(Flash::NONE) && 82 flash != static_cast<jint>(Flash::TIMED) && 83 flash != static_cast<jint>(Flash::HARDWARE)) { 84 ALOGE("Invalid flash parameter %d.", flash); 85 valid = false; 86 } 87 88 if (brightness != static_cast<jint>(Brightness::USER) && 89 brightness != static_cast<jint>(Brightness::SENSOR) && 90 brightness != static_cast<jint>(Brightness::LOW_PERSISTENCE)) { 91 ALOGE("Invalid brightness parameter %d.", brightness); 92 valid = false; 93 } 94 95 if (brightness == static_cast<jint>(Brightness::LOW_PERSISTENCE) && 96 light != static_cast<jint>(Type::BACKLIGHT)) { 97 ALOGE("Cannot set low-persistence mode for non-backlight device."); 98 valid = false; 99 } 100 101 return valid; 102} 103 104static LightState constructState( 105 jint colorARGB, 106 jint flashMode, 107 jint onMS, 108 jint offMS, 109 jint brightnessMode){ 110 Flash flash = static_cast<Flash>(flashMode); 111 Brightness brightness = static_cast<Brightness>(brightnessMode); 112 113 LightState state{}; 114 115 if (brightness == Brightness::LOW_PERSISTENCE) { 116 state.flashMode = Flash::NONE; 117 } else { 118 // Only set non-brightness settings when not in low-persistence mode 119 state.flashMode = flash; 120 state.flashOnMs = onMS; 121 state.flashOffMs = offMS; 122 } 123 124 state.color = colorARGB; 125 state.brightnessMode = brightness; 126 127 return state; 128} 129 130static void processReturn( 131 const Return<Status> &ret, 132 Type type, 133 const LightState &state) { 134 if (!ret.isOk()) { 135 ALOGE("Failed to issue set light command."); 136 LightHal::disassociate(); 137 return; 138 } 139 140 switch (static_cast<Status>(ret)) { 141 case Status::SUCCESS: 142 break; 143 case Status::LIGHT_NOT_SUPPORTED: 144 ALOGE("Light requested not available on this device. %d", type); 145 break; 146 case Status::BRIGHTNESS_NOT_SUPPORTED: 147 ALOGE("Brightness parameter not supported on this device: %d", 148 state.brightnessMode); 149 break; 150 case Status::UNKNOWN: 151 default: 152 ALOGE("Unknown error setting light."); 153 } 154} 155 156static void setLight_native( 157 JNIEnv* /* env */, 158 jobject /* clazz */, 159 jint light, 160 jint colorARGB, 161 jint flashMode, 162 jint onMS, 163 jint offMS, 164 jint brightnessMode) { 165 166 if (!validate(light, flashMode, brightnessMode)) { 167 return; 168 } 169 170 sp<ILight> hal = LightHal::associate(); 171 172 if (hal == nullptr) { 173 return; 174 } 175 176 Type type = static_cast<Type>(light); 177 LightState state = constructState( 178 colorARGB, flashMode, onMS, offMS, brightnessMode); 179 180 { 181 ALOGD_IF_SLOW(50, "Excessive delay setting light"); 182 Return<Status> ret = hal->setLight(type, state); 183 processReturn(ret, type, state); 184 } 185} 186 187static const JNINativeMethod method_table[] = { 188 { "setLight_native", "(IIIIII)V", (void*)setLight_native }, 189}; 190 191int register_android_server_LightsService(JNIEnv *env) { 192 return jniRegisterNativeMethods(env, "com/android/server/lights/LightsService", 193 method_table, NELEM(method_table)); 194} 195 196}; 197