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_transaction.h"
27 #include "transaction/rs_interfaces.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_LABEL UserIam::Common::LABEL_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(
101 colorBytes[RIndex], colorBytes[GIndex], colorBytes[BIndex], 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 ¶m)
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 = std::shared_ptr<RenderContext>(RenderContextFactory::GetInstance().CreateNewEngine());
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) {
195 .centerXInPx = centerXInPx,
196 .centerYInPy = centerYInPx,
197 .radius = radius,
198 .color = color,
199 .alpha = 0,
200 .frameWidth = width,
201 .frameHeight = height
202 };
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 uint32_t brightness = DisplayPowerMgr::DisplayPowerMgrClient::GetInstance().GetDeviceBrightness();
237 IF_FALSE_LOGE_AND_RETURN_VAL(brightness != INVALID_BRIGHTNESS, ResultCode::GENERAL_ERROR);
238 IAM_LOGI("get device brightness %{public}u", brightness);
239
240 if (brightness == brightness_) {
241 IAM_LOGI("brightness is same, no need redraw");
242 return ResultCode::SUCCESS;
243 }
244 brightness_ = brightness;
245
246 uint32_t alpha;
247 ResultCode result = GetBackgroundAlpha(brightness_, alpha);
248 IF_FALSE_LOGE_AND_RETURN_VAL(result == ResultCode::SUCCESS, ResultCode::GENERAL_ERROR);
249 canvasParam_.alpha = alpha;
250
251 auto surfaceFrame = rsSurface_->RequestFrame(canvasParam_.frameWidth, canvasParam_.frameHeight);
252 IF_FALSE_LOGE_AND_RETURN_VAL(surfaceFrame != nullptr, ResultCode::GENERAL_ERROR);
253 auto skSurface = surfaceFrame->GetSurface();
254 IF_FALSE_LOGE_AND_RETURN_VAL(skSurface != nullptr, ResultCode::GENERAL_ERROR);
255
256 auto canvas = Common::MakeShared<RSPaintFilterCanvas>(skSurface.get());
257 IF_FALSE_LOGE_AND_RETURN_VAL(canvas != nullptr, ResultCode::GENERAL_ERROR);
258 auto drawCanvasResult = DrawCanvas(canvas, canvasParam_);
259 IF_FALSE_LOGE_AND_RETURN_VAL(drawCanvasResult == ResultCode::SUCCESS, ResultCode::GENERAL_ERROR);
260
261 rsSurface_->FlushFrame(surfaceFrame);
262 auto transactionPolicy = RSTransactionProxy::GetInstance();
263 transactionPolicy->FlushImplicitTransaction();
264
265 IAM_LOGI("success");
266 return ResultCode::SUCCESS;
267 }
268
TurnOnSensorIllumination()269 ResultCode SensorIlluminationTask::TurnOnSensorIllumination()
270 {
271 std::lock_guard<std::recursive_mutex> lock(recursiveMutex_);
272 IAM_LOGI("start");
273
274 IF_FALSE_LOGE_AND_RETURN_VAL(rsSurfaceNode_ != nullptr, ResultCode::GENERAL_ERROR);
275
276 if (ScreenStateMonitor::GetInstance().GetScreenOn() == false) {
277 IAM_LOGI("screen is not on, no need turn on display");
278 return ResultCode::SUCCESS;
279 }
280
281 if (isIlluminationOn_) {
282 IAM_LOGI("illumination already on");
283 return ResultCode::SUCCESS;
284 }
285
286 ResultCode drawResult = DrawSurfaceNode();
287 IF_FALSE_LOGE_AND_RETURN_VAL(drawResult == ResultCode::SUCCESS, ResultCode::GENERAL_ERROR);
288
289 timer_.Unregister(currTimerId_);
290 currTimerId_ = timer_.Register(
291 [weak_self = weak_from_this()]() {
292 auto self = weak_self.lock();
293 if (self == nullptr) {
294 IAM_LOGE("object is released");
295 return;
296 }
297 self->OnDisplayTimeOut();
298 },
299 MAX_DISPLAY_TIME, true);
300
301 IF_FALSE_LOGE_AND_RETURN_VAL(defaultScreenId_ != Rosen::INVALID_SCREEN_ID, ResultCode::GENERAL_ERROR);
302 rsSurfaceNode_->SetPositionZ(MAX_ZORDER);
303 rsSurfaceNode_->AttachToDisplay(defaultScreenId_);
304 OHOS::Rosen::RSTransaction::FlushImplicitTransaction();
305
306 isIlluminationOn_ = true;
307
308 IAM_LOGI("success");
309 return ResultCode::SUCCESS;
310 }
311
TurnOffSensorIllumination()312 ResultCode SensorIlluminationTask::TurnOffSensorIllumination()
313 {
314 std::lock_guard<std::recursive_mutex> lock(recursiveMutex_);
315 IAM_LOGI("start");
316
317 IF_FALSE_LOGE_AND_RETURN_VAL(rsSurfaceNode_ != nullptr, ResultCode::GENERAL_ERROR);
318
319 if (!isIlluminationOn_) {
320 IAM_LOGI("illumination already off");
321 return ResultCode::SUCCESS;
322 }
323
324 timer_.Unregister(currTimerId_);
325
326 IF_FALSE_LOGE_AND_RETURN_VAL(defaultScreenId_ != Rosen::INVALID_SCREEN_ID, ResultCode::GENERAL_ERROR);
327 rsSurfaceNode_->DetachToDisplay(defaultScreenId_);
328 OHOS::Rosen::RSTransaction::FlushImplicitTransaction();
329
330 isIlluminationOn_ = false;
331
332 IAM_LOGI("success");
333 return ResultCode::SUCCESS;
334 }
335
OnDisplayTimeOut()336 void SensorIlluminationTask::OnDisplayTimeOut()
337 {
338 IAM_LOGI("start");
339 TurnOffSensorIllumination();
340 }
341
RegisterDestructCallback(DestructCallback destructCallback)342 void SensorIlluminationTask::RegisterDestructCallback(DestructCallback destructCallback)
343 {
344 destructCallback_ = destructCallback;
345 }
346
GetSensorIlluminationTask()347 std::shared_ptr<ISensorIlluminationTask> GetSensorIlluminationTask()
348 {
349 return Common::MakeShared<SensorIlluminationTask>();
350 }
351 } // namespace FingerprintAuth
352 } // namespace UserIam
353 } // namespace OHOS