1 /*
2  * Copyright (C) 2019 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 "light"
18 
19 #include <android-base/file.h>
20 #include <hardware/lights.h>
21 #include <log/log.h>
22 
23 #include "LightExt.h"
24 
25 namespace hardware {
26 namespace google {
27 namespace light {
28 namespace V1_1 {
29 namespace implementation {
30 using ::android::hardware::light::V2_0::Brightness;
31 
32 #define HBM_OFF "0"
33 #define HBM_ON  "1"
34 #define HBM_SV  "2"
35 
applyHBM()36 Return<Status> LightExt::applyHBM() {
37   if (!mHasHbmNode) return Status::UNKNOWN;
38 
39   /* skip if no change */
40   if (mRegHBM == mCurHBM && mRegHBMSV == mCurHBMSV) return Status::SUCCESS;
41 
42   //          off
43   //        <--------
44   //    0,0 --------> 0,1
45   //    | ^   sv      ^ |
46   // hbm| | off    nop| |nop
47   //    V |   sv      | V
48   //   1,0 -------->  1,1
49   //       <--------
50   //          hbm
51 
52   // Transition from (mCurHBM, mCurHBMSV) --> (mRegHBM, mRegHBMSV)
53   const char *action = NULL;
54 
55   if (!mRegHBM && !mRegHBMSV) {
56     // to state (0,0)
57     action = HBM_OFF;
58   } else if (mRegHBMSV) {
59     // to state (0,1) or (1,1).
60     if (!mCurHBMSV)
61       action = HBM_SV;
62   } else {
63       // to state (1,0)
64       action = HBM_ON;
65   }
66 
67   if (action) {
68     if (!android::base::WriteStringToFile(action, kHighBrightnessModeNode)) {
69       ALOGE("write %s to HBM sysfs file failed!", action);
70       return Status::UNKNOWN;
71     }
72 
73     ALOGD("write %s to HBM sysfs file succeeded", action);
74   }
75 
76   mCurHBM = mRegHBM;
77   mCurHBMSV = mRegHBMSV;
78 
79   return Status::SUCCESS;
80 }
81 
82 // Methods from ::android::hardware::light::V2_0::ILight follow.
setLight(Type type,const LightState & state)83 Return<Status> LightExt::setLight(Type type, const LightState& state) {
84   if (type == Type::BACKLIGHT) {
85     if (state.brightnessMode == Brightness::LOW_PERSISTENCE) {
86       mRegHBM = false;
87       mRegHBMSV = false;
88       applyHBM();
89       mVRMode = true;
90     } else {
91       // VR has higher priority than HBM. We cannot update HBM status
92       // when VR is enabled. Disable VR before apply HBM mode
93       Status status = mLight->setLight(type, state);
94       mVRMode = false;
95       applyHBM();
96       return status;
97     }
98   }
99   return mLight->setLight(type, state);
100 }
101 
102 // Methods from ::hardware::google::light::V1_0::ILight follow.
setHbm(bool on)103 Return<Status> LightExt::setHbm(bool on) {
104   /* save the request state */
105   mRegHBM = on;
106 
107   if (mVRMode) return Status::UNKNOWN;
108 
109   Status status = applyHBM();
110 
111   if (status != Status::SUCCESS)
112     mRegHBM = mCurHBM;
113 
114   return status;
115 }
116 
117 // Methods from ::hardware::google::light::V1_1::ILight follow.
setHbmSv(bool on)118 Return<Status> LightExt::setHbmSv(bool on) {
119   /* save the request state */
120   mRegHBMSV = on;
121 
122   if (mVRMode) return Status::UNKNOWN;
123 
124   Status status = applyHBM();
125 
126   if (status != Status::SUCCESS)
127     mRegHBMSV = mCurHBMSV;
128 
129   return status;
130 }
131 
getHbmSv()132 Return<bool> LightExt::getHbmSv() {
133   return mCurHBMSV;
134 }
135 
136 }  // namespace implementation
137 }  // namespace V1_1
138 }  // namespace light
139 }  // namespace google
140 }  // namespace hardware
141