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 
30 namespace android {
31 
32 using Brightness = ::android::hardware::light::V2_0::Brightness;
33 using Flash      = ::android::hardware::light::V2_0::Flash;
34 using ILight     = ::android::hardware::light::V2_0::ILight;
35 using LightState = ::android::hardware::light::V2_0::LightState;
36 using Status     = ::android::hardware::light::V2_0::Status;
37 using Type       = ::android::hardware::light::V2_0::Type;
38 template<typename T>
39 using Return     = ::android::hardware::Return<T>;
40 
41 class LightHal {
42 private:
43     static sp<ILight> sLight;
44     static bool sLightInit;
45 
LightHal()46     LightHal() {}
47 
48 public:
disassociate()49     static void disassociate() {
50         sLightInit = false;
51         sLight = nullptr;
52     }
53 
associate()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 
70 sp<ILight> LightHal::sLight = nullptr;
71 bool LightHal::sLightInit = false;
72 
validate(jint light,jint flash,jint brightness)73 static 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 
constructState(jint colorARGB,jint flashMode,jint onMS,jint offMS,jint brightnessMode)104 static 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 
processReturn(const Return<Status> & ret,Type type,const LightState & state)130 static 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 
setLight_native(JNIEnv *,jobject,jint light,jint colorARGB,jint flashMode,jint onMS,jint offMS,jint brightnessMode)156 static 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 
187 static const JNINativeMethod method_table[] = {
188     { "setLight_native", "(IIIIII)V", (void*)setLight_native },
189 };
190 
register_android_server_LightsService(JNIEnv * env)191 int 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