1 /*
2  * Copyright (c) 2023 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include "sensor_illumination_task.h"
17 
18 #include "common_event_manager.h"
19 #include "common_event_subscriber.h"
20 #include "common_event_support.h"
21 #ifdef CONFIG_USE_DISPLAY_MANAGER_COMPONENT
22 #include "display_power_mgr_client.h"
23 #endif
24 #include "iservice_registry.h"
25 #include "pipeline/rs_render_thread.h"
26 #include "system_ability_definition.h"
27 #include "system_ability_status_change_stub.h"
28 #include "transaction/rs_interfaces.h"
29 #include "transaction/rs_transaction.h"
30 #include "ui/rs_surface_extractor.h"
31 
32 #include "iam_check.h"
33 #include "iam_logger.h"
34 #include "iam_ptr.h"
35 
36 #include "sa_command_manager.h"
37 #include "screen_state_monitor.h"
38 
39 #define LOG_TAG "FINGERPRINT_AUTH_SA"
40 
41 namespace OHOS {
42 namespace UserIam {
43 namespace FingerprintAuth {
44 using namespace EventFwk;
45 using namespace AAFwk;
46 using namespace UserAuth;
47 using namespace Rosen;
48 
49 namespace {
50 constexpr uint32_t MAX_DISPLAY_TIME = 1000; // ms
51 constexpr uint32_t BRIGHTNESS_INDEX = 0;
52 constexpr uint32_t ALPHA_INDEX = 1;
53 constexpr uint32_t THOUSAND = 1000l; // center X and Y in per thousand
54 constexpr float MAX_ZORDER = 100000.0f;
55 constexpr uint8_t BRIGHTNESS_AND_ALPHA[][2] = { { 4, 234 }, { 6, 229 }, { 8, 219 }, { 10, 220 }, { 12, 216 },
56     { 14, 211 }, { 16, 208 }, { 20, 205 }, { 24, 187 }, { 28, 176 }, { 30, 170 }, { 34, 163 }, { 40, 159 }, { 46, 142 },
57     { 50, 140 }, { 56, 140 }, { 64, 125 }, { 74, 121 }, { 84, 111 }, { 94, 101 }, { 104, 92 }, { 114, 81 }, { 124, 81 },
58     { 134, 69 }, { 144, 68 }, { 154, 58 }, { 164, 56 }, { 174, 46 }, { 184, 44 }, { 194, 35 }, { 204, 34 }, { 214, 30 },
59     { 224, 22 }, { 234, 23 }, { 244, 18 }, { 248, 0 }, { 255, 0 } };
GetBackgroundAlpha(int32_t currScreenBrightness, uint32_t &outAlpha)60 ResultCode GetBackgroundAlpha(int32_t currScreenBrightness, uint32_t &outAlpha)
61 {
62     for (uint32_t i = 0; i < sizeof(BRIGHTNESS_AND_ALPHA) / sizeof(BRIGHTNESS_AND_ALPHA[0]); i++) {
63         if (currScreenBrightness > BRIGHTNESS_AND_ALPHA[i][BRIGHTNESS_INDEX]) {
64             continue;
65         } else if (currScreenBrightness == BRIGHTNESS_AND_ALPHA[i][BRIGHTNESS_INDEX] || i == 0) {
66             outAlpha = BRIGHTNESS_AND_ALPHA[i][ALPHA_INDEX];
67         } else {
68             // linear interpolation
69             float gapBrightnessDiff =
70                 BRIGHTNESS_AND_ALPHA[i][BRIGHTNESS_INDEX] - BRIGHTNESS_AND_ALPHA[i - 1][BRIGHTNESS_INDEX];
71             float gapAlphaDiff = BRIGHTNESS_AND_ALPHA[i][ALPHA_INDEX] - BRIGHTNESS_AND_ALPHA[i - 1][ALPHA_INDEX];
72             float slope = gapAlphaDiff / gapBrightnessDiff;
73             float currBrightnessDiff = currScreenBrightness - BRIGHTNESS_AND_ALPHA[i - 1][BRIGHTNESS_INDEX];
74             float currAlphaDiff = slope * currBrightnessDiff;
75             outAlpha = BRIGHTNESS_AND_ALPHA[i - 1][ALPHA_INDEX] + static_cast<uint32_t>(currAlphaDiff);
76         }
77         IAM_LOGI("brightness %{public}d to alpha %{public}u", currScreenBrightness, outAlpha);
78         return ResultCode::SUCCESS;
79     }
80     IAM_LOGE("brightness mismatch");
81     return ResultCode::GENERAL_ERROR;
82 }
83 
84 #ifndef USE_ROSEN_DRAWING
ConvertToSkColor(uint32_t color)85 SkColor ConvertToSkColor(uint32_t color)
86 {
87     uint8_t *colorBytes = static_cast<uint8_t *>(static_cast<void *>(&color));
88     constexpr uint32_t RIndex = 0;
89     constexpr uint32_t GIndex = 1;
90     constexpr uint32_t BIndex = 2;
91     constexpr uint32_t AIndex = 3;
92     return SkColorSetARGB(colorBytes[AIndex], colorBytes[RIndex], colorBytes[GIndex], colorBytes[BIndex]);
93 }
94 #else
ConvertToDrawingColor(uint32_t color)95 Drawing::ColorQuad ConvertToDrawingColor(uint32_t color)
96 {
97     uint8_t *colorBytes = static_cast<uint8_t *>(static_cast<void *>(&color));
98     constexpr uint32_t RIndex = 0;
99     constexpr uint32_t GIndex = 1;
100     constexpr uint32_t BIndex = 2;
101     constexpr uint32_t AIndex = 3;
102     return Drawing::Color::ColorQuadSetARGB(colorBytes[RIndex], colorBytes[GIndex], colorBytes[BIndex],
103         colorBytes[AIndex]);
104 }
105 #endif
106 
DrawCanvas(std::shared_ptr<RSPaintFilterCanvas> canvas, const CanvasParam &param)107 ResultCode DrawCanvas(std::shared_ptr<RSPaintFilterCanvas> canvas, const CanvasParam &param)
108 {
109     IF_FALSE_LOGE_AND_RETURN_VAL(canvas != nullptr, ResultCode::GENERAL_ERROR);
110 
111 #ifndef USE_ROSEN_DRAWING
112     canvas->clear(SkColorSetARGB(param.alpha, 0x00, 0x00, 0x00));
113 
114     SkPaint paint;
115     paint.setStyle(SkPaint::kFill_Style);
116     paint.setAntiAlias(true);
117     paint.setColor(ConvertToSkColor(param.color));
118 
119     canvas->drawCircle(SkPoint::Make(param.centerXInPx, param.centerYInPy), param.radius, paint);
120 #else
121     canvas->Clear(Drawing::Color::ColorQuadSetARGB(0x00, 0x00, 0x00, param.alpha));
122 
123     Drawing::Brush brush;
124     brush.SetAntiAlias(true);
125     brush.SetColor(ConvertToDrawingColor(param.color));
126 
127     canvas->AttachBrush(brush);
128     canvas->DrawCircle(Drawing::Point(param.centerXInPx, param.centerYInPy), param.radius);
129     canvas->DetachBrush();
130 #endif
131     return ResultCode::SUCCESS;
132 }
133 
convertThousandthToPx(uint32_t relativeLength, uint32_t fullLength, uint32_t &pxLength)134 bool convertThousandthToPx(uint32_t relativeLength, uint32_t fullLength, uint32_t &pxLength)
135 {
136     uint64_t pxLengthUint64 = static_cast<uint64_t>(relativeLength) * static_cast<uint64_t>(fullLength) / THOUSAND;
137     if (pxLengthUint64 > std::numeric_limits<uint32_t>::max()) {
138         IAM_LOGE("pxLengthUint64 is more than UINT32_MAX");
139         return false;
140     }
141     pxLength = static_cast<uint32_t>(pxLengthUint64);
142     return true;
143 }
144 } // namespace
145 
SensorIlluminationTask()146 SensorIlluminationTask::SensorIlluminationTask() : timer_("sensor_illumination_timer")
147 {
148     ScreenStateMonitor::GetInstance().Subscribe();
149     timer_.Setup();
150 }
151 
~SensorIlluminationTask()152 SensorIlluminationTask::~SensorIlluminationTask()
153 {
154     ScreenStateMonitor::GetInstance().Unsubscribe();
155     timer_.Unregister(currTimerId_);
156     timer_.Shutdown();
157     if (destructCallback_ != nullptr) {
158         destructCallback_();
159     }
160 }
161 
EnableSensorIllumination(uint32_t centerX, uint32_t centerY, uint32_t radius, uint32_t color)162 ResultCode SensorIlluminationTask::EnableSensorIllumination(uint32_t centerX, uint32_t centerY, uint32_t radius,
163     uint32_t color)
164 {
165     std::lock_guard<std::recursive_mutex> lock(recursiveMutex_);
166     IAM_LOGI("start");
167 
168     RSSurfaceNodeConfig config = { .SurfaceNodeName = "FingerprintSenor" };
169 
170     auto rsSurfaceNode = RSSurfaceNode::Create(config, RSSurfaceNodeType::SELF_DRAWING_WINDOW_NODE);
171     IF_FALSE_LOGE_AND_RETURN_VAL(rsSurfaceNode != nullptr, ResultCode::GENERAL_ERROR);
172 
173     auto defaultDisplay = DisplayManager::GetInstance().GetDefaultDisplay();
174     IF_FALSE_LOGE_AND_RETURN_VAL(defaultDisplay != nullptr, ResultCode::GENERAL_ERROR);
175 
176     int32_t width = defaultDisplay->GetWidth();
177     int32_t height = defaultDisplay->GetHeight();
178     rsSurfaceNode->SetBounds(0, 0, width, height);
179     rsSurfaceNode->SetFingerprint(true);
180 
181     std::shared_ptr<RSSurface> rsSurface = RSSurfaceExtractor::ExtractRSSurface(rsSurfaceNode);
182     IF_FALSE_LOGE_AND_RETURN_VAL(rsSurface != nullptr, ResultCode::GENERAL_ERROR);
183 
184     auto renderContext = Common::MakeShared<RenderContext>();
185     IF_FALSE_LOGE_AND_RETURN_VAL(renderContext != nullptr, ResultCode::GENERAL_ERROR);
186     renderContext->InitializeEglContext();
187     rsSurface->SetRenderContext(renderContext.get());
188 
189     uint32_t centerXInPx = 0;
190     bool convertRetX = convertThousandthToPx(centerX, defaultDisplay->GetWidth(), centerXInPx);
191     IF_FALSE_LOGE_AND_RETURN_VAL(convertRetX == true, ResultCode::GENERAL_ERROR);
192     uint32_t centerYInPx = 0;
193     bool convertRetY = convertThousandthToPx(centerY, defaultDisplay->GetHeight(), centerYInPx);
194     IF_FALSE_LOGE_AND_RETURN_VAL(convertRetY == true, ResultCode::GENERAL_ERROR);
195 
196     canvasParam_ = (CanvasParam) { .centerXInPx = centerXInPx,
197         .centerYInPy = centerYInPx,
198         .radius = radius,
199         .color = color,
200         .alpha = 0,
201         .frameWidth = width,
202         .frameHeight = height };
203 
204     defaultScreenId_ = Rosen::RSInterfaces::GetInstance().GetDefaultScreenId();
205     defaultDisplayId_ = defaultDisplay->GetId();
206     rsSurfaceNode_ = rsSurfaceNode;
207     rsSurface_ = rsSurface;
208     renderContext_ = renderContext;
209 
210     ResultCode drawResult = DrawSurfaceNode();
211     IF_FALSE_LOGE_AND_RETURN_VAL(drawResult == ResultCode::SUCCESS, ResultCode::GENERAL_ERROR);
212 
213     IAM_LOGI("success");
214     return ResultCode::SUCCESS;
215 }
216 
DisableSensorIllumination()217 ResultCode SensorIlluminationTask::DisableSensorIllumination()
218 {
219     std::lock_guard<std::recursive_mutex> lock(recursiveMutex_);
220     IAM_LOGI("start");
221 
222     TurnOffSensorIllumination();
223     rsSurfaceNode_ = nullptr;
224 
225     ScreenStateMonitor::GetInstance().Unsubscribe();
226     IAM_LOGI("success");
227     return ResultCode::SUCCESS;
228 }
229 
DrawSurfaceNode()230 ResultCode SensorIlluminationTask::DrawSurfaceNode()
231 {
232     IF_FALSE_LOGE_AND_RETURN_VAL(rsSurface_ != nullptr, ResultCode::GENERAL_ERROR);
233 
234     IAM_LOGI("start");
235 
236 #ifdef CONFIG_USE_DISPLAY_MANAGER_COMPONENT
237     uint32_t brightness = DisplayPowerMgr::DisplayPowerMgrClient::GetInstance().GetDeviceBrightness();
238 #else
239     uint32_t brightness = INVALID_BRIGHTNESS;
240 #endif
241     IF_FALSE_LOGE_AND_RETURN_VAL(brightness != INVALID_BRIGHTNESS, ResultCode::GENERAL_ERROR);
242     IAM_LOGI("get device brightness %{public}u", brightness);
243 
244     if (brightness == brightness_) {
245         IAM_LOGI("brightness is same, no need redraw");
246         return ResultCode::SUCCESS;
247     }
248     brightness_ = brightness;
249 
250     uint32_t alpha;
251     ResultCode result = GetBackgroundAlpha(brightness_, alpha);
252     IF_FALSE_LOGE_AND_RETURN_VAL(result == ResultCode::SUCCESS, ResultCode::GENERAL_ERROR);
253     canvasParam_.alpha = alpha;
254 
255     auto surfaceFrame = rsSurface_->RequestFrame(canvasParam_.frameWidth, canvasParam_.frameHeight);
256     IF_FALSE_LOGE_AND_RETURN_VAL(surfaceFrame != nullptr, ResultCode::GENERAL_ERROR);
257     auto skSurface = surfaceFrame->GetSurface();
258     IF_FALSE_LOGE_AND_RETURN_VAL(skSurface != nullptr, ResultCode::GENERAL_ERROR);
259 
260     auto canvas = Common::MakeShared<RSPaintFilterCanvas>(skSurface.get());
261     IF_FALSE_LOGE_AND_RETURN_VAL(canvas != nullptr, ResultCode::GENERAL_ERROR);
262     auto drawCanvasResult = DrawCanvas(canvas, canvasParam_);
263     IF_FALSE_LOGE_AND_RETURN_VAL(drawCanvasResult == ResultCode::SUCCESS, ResultCode::GENERAL_ERROR);
264 
265     rsSurface_->FlushFrame(surfaceFrame);
266     auto transactionPolicy = RSTransactionProxy::GetInstance();
267     transactionPolicy->FlushImplicitTransaction();
268 
269     IAM_LOGI("success");
270     return ResultCode::SUCCESS;
271 }
272 
TurnOnSensorIllumination()273 ResultCode SensorIlluminationTask::TurnOnSensorIllumination()
274 {
275     std::lock_guard<std::recursive_mutex> lock(recursiveMutex_);
276     IAM_LOGI("start");
277 
278     IF_FALSE_LOGE_AND_RETURN_VAL(rsSurfaceNode_ != nullptr, ResultCode::GENERAL_ERROR);
279 
280     if (ScreenStateMonitor::GetInstance().GetScreenOn() == false) {
281         IAM_LOGI("screen is not on, no need turn on display");
282         return ResultCode::SUCCESS;
283     }
284 
285     if (isIlluminationOn_) {
286         IAM_LOGI("illumination already on");
287         return ResultCode::SUCCESS;
288     }
289 
290     ResultCode drawResult = DrawSurfaceNode();
291     IF_FALSE_LOGE_AND_RETURN_VAL(drawResult == ResultCode::SUCCESS, ResultCode::GENERAL_ERROR);
292 
293     timer_.Unregister(currTimerId_);
294     currTimerId_ = timer_.Register(
295         [weak_self = weak_from_this()]() {
296             auto self = weak_self.lock();
297             if (self == nullptr) {
298                 IAM_LOGE("object is released");
299                 return;
300             }
301             self->OnDisplayTimeOut();
302         },
303         MAX_DISPLAY_TIME, true);
304 
305     IF_FALSE_LOGE_AND_RETURN_VAL(defaultScreenId_ != Rosen::INVALID_SCREEN_ID, ResultCode::GENERAL_ERROR);
306     rsSurfaceNode_->SetPositionZ(MAX_ZORDER);
307     rsSurfaceNode_->AttachToDisplay(defaultScreenId_);
308     OHOS::Rosen::RSTransaction::FlushImplicitTransaction();
309 
310     isIlluminationOn_ = true;
311 
312     IAM_LOGI("success");
313     return ResultCode::SUCCESS;
314 }
315 
TurnOffSensorIllumination()316 ResultCode SensorIlluminationTask::TurnOffSensorIllumination()
317 {
318     std::lock_guard<std::recursive_mutex> lock(recursiveMutex_);
319     IAM_LOGI("start");
320 
321     IF_FALSE_LOGE_AND_RETURN_VAL(rsSurfaceNode_ != nullptr, ResultCode::GENERAL_ERROR);
322 
323     if (!isIlluminationOn_) {
324         IAM_LOGI("illumination already off");
325         return ResultCode::SUCCESS;
326     }
327 
328     timer_.Unregister(currTimerId_);
329 
330     IF_FALSE_LOGE_AND_RETURN_VAL(defaultScreenId_ != Rosen::INVALID_SCREEN_ID, ResultCode::GENERAL_ERROR);
331     rsSurfaceNode_->DetachToDisplay(defaultScreenId_);
332     OHOS::Rosen::RSTransaction::FlushImplicitTransaction();
333 
334     isIlluminationOn_ = false;
335 
336     IAM_LOGI("success");
337     return ResultCode::SUCCESS;
338 }
339 
OnDisplayTimeOut()340 void SensorIlluminationTask::OnDisplayTimeOut()
341 {
342     IAM_LOGI("start");
343     TurnOffSensorIllumination();
344 }
345 
RegisterDestructCallback(DestructCallback destructCallback)346 void SensorIlluminationTask::RegisterDestructCallback(DestructCallback destructCallback)
347 {
348     destructCallback_ = destructCallback;
349 }
350 
GetSensorIlluminationTask()351 std::shared_ptr<ISensorIlluminationTask> GetSensorIlluminationTask()
352 {
353     return Common::MakeShared<SensorIlluminationTask>();
354 }
355 } // namespace FingerprintAuth
356 } // namespace UserIam
357 } // namespace OHOS