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