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