1cb69b360Sopenharmony_ci/*
2cb69b360Sopenharmony_ci * Copyright (c) 2021 Huawei Device Co., Ltd.
3cb69b360Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License");
4cb69b360Sopenharmony_ci * you may not use this file except in compliance with the License.
5cb69b360Sopenharmony_ci * You may obtain a copy of the License at
6cb69b360Sopenharmony_ci *
7cb69b360Sopenharmony_ci *     http://www.apache.org/licenses/LICENSE-2.0
8cb69b360Sopenharmony_ci *
9cb69b360Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software
10cb69b360Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS,
11cb69b360Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12cb69b360Sopenharmony_ci * See the License for the specific language governing permissions and
13cb69b360Sopenharmony_ci * limitations under the License.
14cb69b360Sopenharmony_ci */
15cb69b360Sopenharmony_ci
16cb69b360Sopenharmony_ci#include <stdlib.h>
17cb69b360Sopenharmony_ci
18cb69b360Sopenharmony_ci#include <common.h>
19cb69b360Sopenharmony_ci#include <ohos_errno.h>
20cb69b360Sopenharmony_ci#include <pthread.h>
21cb69b360Sopenharmony_ci#include <securec.h>
22cb69b360Sopenharmony_ci
23cb69b360Sopenharmony_ci#include "hilog_wrapper.h"
24cb69b360Sopenharmony_ci#include "power/suspend_controller.h"
25cb69b360Sopenharmony_ci#include "running_lock_entry.h"
26cb69b360Sopenharmony_ci
27cb69b360Sopenharmony_cistatic pthread_mutex_t g_mutex = PTHREAD_MUTEX_INITIALIZER;
28cb69b360Sopenharmony_cistatic Vector g_runningLocks[RUNNINGLOCK_BUTT];
29cb69b360Sopenharmony_cistatic const char * const g_runningLockNames[RUNNINGLOCK_BUTT] = {
30cb69b360Sopenharmony_ci    "OHOSPowerMgr.Screen",
31cb69b360Sopenharmony_ci    "OHOSPowerMgr.Background",
32cb69b360Sopenharmony_ci    "OHOSPowerMgr.Proximity",
33cb69b360Sopenharmony_ci};
34cb69b360Sopenharmony_ci
35cb69b360Sopenharmony_cistatic RunningLockEntry *DupRunningLockEntry(RunningLockEntry *entry)
36cb69b360Sopenharmony_ci{
37cb69b360Sopenharmony_ci    RunningLockEntry *e = (RunningLockEntry *)malloc(sizeof(RunningLockEntry));
38cb69b360Sopenharmony_ci    if (e == NULL) {
39cb69b360Sopenharmony_ci        POWER_HILOGE("Failed allocate running lock entry");
40cb69b360Sopenharmony_ci        return NULL;
41cb69b360Sopenharmony_ci    }
42cb69b360Sopenharmony_ci    if (memcpy_s(e, sizeof(RunningLockEntry), entry, sizeof(RunningLockEntry)) != EOK) {
43cb69b360Sopenharmony_ci        POWER_HILOGE("Failed copy running lock entry");
44cb69b360Sopenharmony_ci        free(e);
45cb69b360Sopenharmony_ci        return NULL;
46cb69b360Sopenharmony_ci    }
47cb69b360Sopenharmony_ci    return e;
48cb69b360Sopenharmony_ci}
49cb69b360Sopenharmony_ci
50cb69b360Sopenharmony_cistatic BOOL AddRunningLockEntryLocked(Vector *vec, RunningLockEntry *entry)
51cb69b360Sopenharmony_ci{
52cb69b360Sopenharmony_ci    int16_t pos = VECTOR_FindByKey(vec, (void *)&entry->identity);
53cb69b360Sopenharmony_ci    if (pos >= 0) {
54cb69b360Sopenharmony_ci        POWER_HILOGD("Already acquired: %s", entry->lock.name);
55cb69b360Sopenharmony_ci        return TRUE;
56cb69b360Sopenharmony_ci    }
57cb69b360Sopenharmony_ci    RunningLockEntry *e = DupRunningLockEntry(entry);
58cb69b360Sopenharmony_ci    if (e == NULL) {
59cb69b360Sopenharmony_ci        POWER_HILOGE("Failed duplicate running lock entry");
60cb69b360Sopenharmony_ci        return FALSE;
61cb69b360Sopenharmony_ci    }
62cb69b360Sopenharmony_ci    pos = VECTOR_Add(vec, (void *)e);
63cb69b360Sopenharmony_ci    if (pos == INVALID_INDEX) {
64cb69b360Sopenharmony_ci        POWER_HILOGE("Failed to add entry to vector");
65cb69b360Sopenharmony_ci        free(e);
66cb69b360Sopenharmony_ci        return FALSE;
67cb69b360Sopenharmony_ci    }
68cb69b360Sopenharmony_ci    POWER_HILOGD("Add running lock entry, name: %s, type: %d", e->lock.name, e->lock.type);
69cb69b360Sopenharmony_ci    if (VECTOR_Num(vec) == 1) {
70cb69b360Sopenharmony_ci        ScAcquireRunningLock(g_runningLockNames[entry->lock.type]);
71cb69b360Sopenharmony_ci    }
72cb69b360Sopenharmony_ci    return TRUE;
73cb69b360Sopenharmony_ci}
74cb69b360Sopenharmony_ci
75cb69b360Sopenharmony_cistatic BOOL RemoveRunningLockEntryLocked(Vector *vec, RunningLockEntry *entry)
76cb69b360Sopenharmony_ci{
77cb69b360Sopenharmony_ci    int16_t pos = VECTOR_FindByKey(vec, (void *)&entry->identity);
78cb69b360Sopenharmony_ci    if (pos < 0) {
79cb69b360Sopenharmony_ci        POWER_HILOGE("Non-existent running lock");
80cb69b360Sopenharmony_ci        return TRUE;
81cb69b360Sopenharmony_ci    }
82cb69b360Sopenharmony_ci    RunningLockEntry *e = (RunningLockEntry *)VECTOR_Swap(vec, pos, NULL);
83cb69b360Sopenharmony_ci    free(e);
84cb69b360Sopenharmony_ci    POWER_HILOGD("Remove running lock entry, name: %s, type: %d", entry->lock.name, entry->lock.type);
85cb69b360Sopenharmony_ci    if (VECTOR_Num(vec) == 0) {
86cb69b360Sopenharmony_ci        ScReleaseRunningLock(g_runningLockNames[entry->lock.type]);
87cb69b360Sopenharmony_ci    }
88cb69b360Sopenharmony_ci    return TRUE;
89cb69b360Sopenharmony_ci}
90cb69b360Sopenharmony_ci
91cb69b360Sopenharmony_cistatic void ShowLocks()
92cb69b360Sopenharmony_ci{
93cb69b360Sopenharmony_ci#ifdef OHOS_DEBUG
94cb69b360Sopenharmony_ci    for (int32_t t = RUNNINGLOCK_SCREEN; t < RUNNINGLOCK_BUTT; t++) {
95cb69b360Sopenharmony_ci        Vector *vec = &g_runningLocks[t];
96cb69b360Sopenharmony_ci        int32_t size = VECTOR_Size(vec);
97cb69b360Sopenharmony_ci        POWER_HILOGD("type: %d, lock num: %d", t, VECTOR_Num(vec));
98cb69b360Sopenharmony_ci        for (int32_t i = 0; i < size; i++) {
99cb69b360Sopenharmony_ci            RunningLockEntry* e = VECTOR_At(vec, i);
100cb69b360Sopenharmony_ci            if (e != NULL) {
101cb69b360Sopenharmony_ci                POWER_HILOGD("No.%d, name: %s, pid: %u, token: %llu",
102cb69b360Sopenharmony_ci                    i, e->lock.name, e->identity.pid, (long long)e->identity.token);
103cb69b360Sopenharmony_ci            }
104cb69b360Sopenharmony_ci        }
105cb69b360Sopenharmony_ci    }
106cb69b360Sopenharmony_ci#endif
107cb69b360Sopenharmony_ci}
108cb69b360Sopenharmony_ci
109cb69b360Sopenharmony_ciint32_t RunningLockMgrAcquireEntry(RunningLockEntry *entry, int32_t timeoutMs)
110cb69b360Sopenharmony_ci{
111cb69b360Sopenharmony_ci    if (IsValidRunningLockEntry(entry) == FALSE) {
112cb69b360Sopenharmony_ci        POWER_HILOGE("Invalid running lock entry");
113cb69b360Sopenharmony_ci        return EC_INVALID;
114cb69b360Sopenharmony_ci    }
115cb69b360Sopenharmony_ci    pthread_mutex_lock(&g_mutex);
116cb69b360Sopenharmony_ci    Vector *vec = &g_runningLocks[entry->lock.type];
117cb69b360Sopenharmony_ci    BOOL ret = AddRunningLockEntryLocked(vec, entry);
118cb69b360Sopenharmony_ci    ShowLocks();
119cb69b360Sopenharmony_ci    pthread_mutex_unlock(&g_mutex);
120cb69b360Sopenharmony_ci    return (ret == TRUE) ? EC_SUCCESS : EC_FAILURE;
121cb69b360Sopenharmony_ci}
122cb69b360Sopenharmony_ci
123cb69b360Sopenharmony_ciint32_t RunningLockMgrReleaseEntry(RunningLockEntry *entry)
124cb69b360Sopenharmony_ci{
125cb69b360Sopenharmony_ci    if (IsValidRunningLockEntry(entry) == FALSE) {
126cb69b360Sopenharmony_ci        POWER_HILOGE("Invalid running lock entry");
127cb69b360Sopenharmony_ci        return EC_INVALID;
128cb69b360Sopenharmony_ci    }
129cb69b360Sopenharmony_ci
130cb69b360Sopenharmony_ci    pthread_mutex_lock(&g_mutex);
131cb69b360Sopenharmony_ci    Vector *vec = &g_runningLocks[entry->lock.type];
132cb69b360Sopenharmony_ci    BOOL ret = RemoveRunningLockEntryLocked(vec, entry);
133cb69b360Sopenharmony_ci    ShowLocks();
134cb69b360Sopenharmony_ci    pthread_mutex_unlock(&g_mutex);
135cb69b360Sopenharmony_ci    return (ret == TRUE) ? EC_SUCCESS : EC_FAILURE;
136cb69b360Sopenharmony_ci}
137cb69b360Sopenharmony_ci
138cb69b360Sopenharmony_ciuint32_t RunningLockMgrGetLockCount(RunningLockType type)
139cb69b360Sopenharmony_ci{
140cb69b360Sopenharmony_ci    uint32_t cnt = 0;
141cb69b360Sopenharmony_ci    if ((type >= 0) && (type < RUNNINGLOCK_BUTT)) {
142cb69b360Sopenharmony_ci        pthread_mutex_lock(&g_mutex);
143cb69b360Sopenharmony_ci        cnt = VECTOR_Num(&g_runningLocks[type]);
144cb69b360Sopenharmony_ci        pthread_mutex_unlock(&g_mutex);
145cb69b360Sopenharmony_ci    }
146cb69b360Sopenharmony_ci    return cnt;
147cb69b360Sopenharmony_ci}
148cb69b360Sopenharmony_ci
149cb69b360Sopenharmony_ciuint32_t RunningLockMgrGetTotalLockCount()
150cb69b360Sopenharmony_ci{
151cb69b360Sopenharmony_ci    uint32_t cnt = 0;
152cb69b360Sopenharmony_ci    pthread_mutex_lock(&g_mutex);
153cb69b360Sopenharmony_ci    for (int32_t t = RUNNINGLOCK_SCREEN; t < RUNNINGLOCK_BUTT; t++) {
154cb69b360Sopenharmony_ci        cnt += VECTOR_Num(&g_runningLocks[t]);
155cb69b360Sopenharmony_ci    }
156cb69b360Sopenharmony_ci    pthread_mutex_unlock(&g_mutex);
157cb69b360Sopenharmony_ci    POWER_HILOGD("Total lock count: %u", cnt);
158cb69b360Sopenharmony_ci    return cnt;
159cb69b360Sopenharmony_ci}
160cb69b360Sopenharmony_ci
161cb69b360Sopenharmony_cistatic const RunningLockIdentity *GetRunningLockIdentity(const RunningLockEntry *entry)
162cb69b360Sopenharmony_ci{
163cb69b360Sopenharmony_ci    return &entry->identity;
164cb69b360Sopenharmony_ci}
165cb69b360Sopenharmony_ci
166cb69b360Sopenharmony_cistatic int32_t RunningLockIdentityCmp(const RunningLockIdentity *a, const RunningLockIdentity *b)
167cb69b360Sopenharmony_ci{
168cb69b360Sopenharmony_ci    return (IsSameRunningLockIdentity(a, b) == TRUE) ? 0 : -1;
169cb69b360Sopenharmony_ci}
170cb69b360Sopenharmony_ci
171cb69b360Sopenharmony_civoid RunningLockMgrInit(void)
172cb69b360Sopenharmony_ci{
173cb69b360Sopenharmony_ci    for (int32_t i = 0; i < RUNNINGLOCK_BUTT; i++) {
174cb69b360Sopenharmony_ci        g_runningLocks[i] = VECTOR_Make((VECTOR_Key)GetRunningLockIdentity, (VECTOR_Compare)RunningLockIdentityCmp);
175cb69b360Sopenharmony_ci    }
176cb69b360Sopenharmony_ci}
177