1/*
2 * Copyright (c) 2022 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 <thread>
17#include <chrono>
18#include <utility>
19
20#include "avsession_log.h"
21#include "app_mgr_constants.h"
22#include "app_manager_adapter.h"
23
24namespace OHOS::AVSession {
25using AppExecFwk::AppProcessData;
26using AppExecFwk::AppProcessState;
27using AppExecFwk::AppMgrResultCode;
28using AppExecFwk::RunningProcessInfo;
29using AppExecFwk::ApplicationState;
30
31AppManagerAdapter::AppManagerAdapter()
32{
33    SLOGI("construct");
34}
35
36AppManagerAdapter::~AppManagerAdapter()
37{
38    SLOGI("destroy");
39}
40
41AppManagerAdapter& AppManagerAdapter::GetInstance()
42{
43    static AppManagerAdapter appManagerAdapter;
44    return appManagerAdapter;
45}
46
47void AppManagerAdapter::Init()
48{
49    appStateCallback_ = new(std::nothrow) AVSessionAppStateCallback();
50    if (appStateCallback_ == nullptr) {
51        SLOGE("no memory");
52        return;
53    }
54    int retryCount = 0;
55    while (retryCount < RETRY_COUNT_MAX) {
56        if (appManager_.RegisterAppStateCallback(appStateCallback_) != AppMgrResultCode::RESULT_OK) {
57            SLOGE("register app state callback failed");
58            retryCount++;
59            std::this_thread::sleep_for(std::chrono::milliseconds(RETRY_INTERVAL_TIME));
60            continue;
61        }
62        break;
63    }
64}
65
66bool AppManagerAdapter::IsAppBackground(int32_t uid, int32_t pid)
67{
68    std::vector<RunningProcessInfo> infos;
69    if (appManager_.GetAllRunningProcesses(infos) != AppMgrResultCode::RESULT_OK) {
70        SLOGE("get all running processes info failed");
71        return false;
72    }
73    for (const auto& info : infos) {
74        if (info.uid_ == uid && info.pid_ == pid && info.state_ == AppProcessState::APP_STATE_BACKGROUND) {
75            SLOGI("uid=%{public}d pid=%{public}d is background", uid, pid);
76            return true;
77        }
78    }
79    SLOGD("uid=%{public}d pid=%{public}d is not background", uid, pid);
80    return false;
81}
82
83void AppManagerAdapter::SetAppStateChangeObserver(const std::function<void(int32_t, int32_t, bool)>& observer)
84{
85    appStateChangeObserver_ = observer;
86}
87
88// LCOV_EXCL_START
89void AppManagerAdapter::AddObservedApp(int32_t uid)
90{
91    std::lock_guard lockGuard(uidLock_);
92    SLOGD("add for uid=%{public}d", uid);
93    observedAppUIDs_.insert(uid);
94}
95// LCOV_EXCL_STOP
96
97void AppManagerAdapter::RemoveObservedApp(int32_t uid)
98{
99    std::lock_guard lockGuard(uidLock_);
100    SLOGD("RemoveObservedApp for uid=%{public}d", uid);
101    observedAppUIDs_.erase(uid);
102}
103
104void AppManagerAdapter::SetServiceCallbackForAppStateChange(const std::function<void(int uid, int state)>& callback)
105{
106    serviceCallbackForAppStateChange_ = callback;
107}
108
109// LCOV_EXCL_START
110void AppManagerAdapter::HandleAppStateChanged(const AppProcessData& appProcessData)
111{
112    {
113        std::lock_guard lockGuard(uidLock_);
114        if (appProcessData.appState == ApplicationState::APP_STATE_FOREGROUND ||
115            appProcessData.appState == ApplicationState::APP_STATE_BACKGROUND) {
116            for (const auto& appData : appProcessData.appDatas) {
117                serviceCallbackForAppStateChange_(appData.uid, static_cast<int>(appProcessData.appState));
118            }
119        }
120    }
121    if (appProcessData.appState == ApplicationState::APP_STATE_TERMINATED) {
122        for (const auto& appData : appProcessData.appDatas) {
123            SLOGI("HandleAppStateChanged remove for uid=%{public}d", static_cast<int>(appData.uid));
124            RemoveObservedApp(appData.uid);
125        }
126    }
127
128    std::set<std::pair<int32_t, int32_t>> appNeedHandleMap;
129    {
130        std::lock_guard lockGuard(uidLock_);
131        for (const auto& appData : appProcessData.appDatas) {
132            SLOGI("bundleName=%{public}s uid=%{public}d pid=%{public}d state=%{public}d",
133                appData.appName.c_str(), appData.uid, appProcessData.pid, appProcessData.appState);
134            auto it = observedAppUIDs_.find(appData.uid);
135            if (it == observedAppUIDs_.end()) {
136                continue;
137            }
138            appNeedHandleMap.insert(std::make_pair(appData.uid, appProcessData.pid));
139        }
140    }
141
142    if (appProcessData.appState == ApplicationState::APP_STATE_BACKGROUND) {
143        if (appStateChangeObserver_) {
144            for (const auto& pair : appNeedHandleMap) {
145                appStateChangeObserver_(pair.first, pair.second, true);
146            }
147        }
148    } else {
149        if (appStateChangeObserver_) {
150            for (const auto& pair : appNeedHandleMap) {
151                appStateChangeObserver_(pair.first, pair.second, false);
152            }
153        }
154    }
155}
156// LCOV_EXCL_STOP
157
158void AVSessionAppStateCallback::OnAppStateChanged(const AppExecFwk::AppProcessData& appProcessData)
159{
160    AppManagerAdapter::GetInstance().HandleAppStateChanged(appProcessData);
161}
162}
163