1 /*
2 * Copyright (c) 2024 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 #include "medialibrary_appstate_observer.h"
16
17 #include <cstddef>
18 #include <sstream>
19 #include <string>
20
21 #include "if_system_ability_manager.h"
22 #include "iservice_registry.h"
23 #include "media_app_uri_permission_column.h"
24 #include "media_app_uri_sensitive_column.h"
25 #include "media_library_manager.h"
26 #include "media_log.h"
27 #include "medialibrary_data_manager.h"
28 #include "medialibrary_errno.h"
29 #include "permission_utils.h"
30 #include "system_ability_definition.h"
31
32 namespace OHOS {
33 namespace Media {
34 using namespace OHOS::AppExecFwk;
35 constexpr int32_t WAITFOR_REVOKE = 2000;
36
GetAppManagerInstance()37 sptr<IAppMgr> MedialibraryAppStateObserverManager::GetAppManagerInstance()
38 {
39 sptr<ISystemAbilityManager> systemAbilityManager =
40 SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
41 CHECK_AND_RETURN_RET_LOG(systemAbilityManager != nullptr, nullptr, "systemAbilityManager is nullptr");
42
43 sptr<IRemoteObject> object = systemAbilityManager->GetSystemAbility(APP_MGR_SERVICE_ID);
44 CHECK_AND_RETURN_RET_LOG(object != nullptr, nullptr, "systemAbilityManager remote object is nullptr");
45 return iface_cast<IAppMgr>(object);
46 }
47
SubscribeAppState()48 void MedialibraryAppStateObserverManager::SubscribeAppState()
49 {
50 MEDIA_INFO_LOG("SubscribeAppState");
51 sptr<IAppMgr> appManager = GetAppManagerInstance();
52 CHECK_AND_RETURN_LOG(appManager != nullptr, "GetAppManagerInstance failed");
53 CHECK_AND_RETURN_INFO_LOG(appStateObserver_ == nullptr, "appStateObserver has been registed");
54
55 appStateObserver_ = new (std::nothrow) MedialibraryAppStateObserver();
56 CHECK_AND_RETURN_LOG(appStateObserver_ != nullptr, "get appStateObserver failed");
57
58 int32_t result = appManager->RegisterApplicationStateObserver(appStateObserver_);
59 if (result != E_SUCCESS) {
60 MEDIA_ERR_LOG("RegistApplicationStateObserver failed");
61 appStateObserver_ = nullptr;
62 return;
63 }
64
65 MEDIA_INFO_LOG("SubscribeAppState success");
66 return;
67 }
68
UnSubscribeAppState()69 void MedialibraryAppStateObserverManager::UnSubscribeAppState()
70 {
71 CHECK_AND_RETURN_LOG(appStateObserver_ != nullptr, "appStateObserver_ is nullptr");
72
73 sptr<IAppMgr> appManager = GetAppManagerInstance();
74 CHECK_AND_RETURN_LOG(appManager != nullptr, "GetAppManagerInstance failed");
75
76 int32_t result = appManager->UnregisterApplicationStateObserver(appStateObserver_);
77 CHECK_AND_RETURN_LOG(result == E_SUCCESS, "UnregisterApplicationStateObserver failed");
78
79 appStateObserver_ = nullptr;
80 MEDIA_INFO_LOG("UnSubscribeAppState success");
81 return;
82 }
83
AddTokenId(int64_t tokenId,bool needRevoke)84 void MedialibraryAppStateObserverManager::AddTokenId(int64_t tokenId, bool needRevoke)
85 {
86 revokeMap_.EnsureInsert(tokenId, needRevoke);
87 }
88
RemoveTokenId(int64_t tokenId)89 void MedialibraryAppStateObserverManager::RemoveTokenId(int64_t tokenId)
90 {
91 revokeMap_.Erase(tokenId);
92 }
93
NeedRevoke(int64_t tokenId)94 bool MedialibraryAppStateObserverManager::NeedRevoke(int64_t tokenId)
95 {
96 bool needRevoke = true;
97 revokeMap_.Find(tokenId, needRevoke);
98 return needRevoke;
99 }
100
IsContainTokenId(int64_t tokenId)101 bool MedialibraryAppStateObserverManager::IsContainTokenId(int64_t tokenId)
102 {
103 bool needRevoke = true;
104 return revokeMap_.Find(tokenId, needRevoke);
105 }
106
GetInstance()107 MedialibraryAppStateObserverManager &MedialibraryAppStateObserverManager::GetInstance()
108 {
109 static MedialibraryAppStateObserverManager instance;
110 return instance;
111 }
112
CountTemporaryPermission(const std::shared_ptr<MediaLibraryRdbStore> rdbStore)113 static int32_t CountTemporaryPermission(const std::shared_ptr<MediaLibraryRdbStore> rdbStore)
114 {
115 NativeRdb::AbsRdbPredicates predicatesUnSubscribe(AppUriPermissionColumn::APP_URI_PERMISSION_TABLE);
116 vector<string> permissionTypes;
117 permissionTypes.emplace_back(to_string(
118 static_cast<int32_t>(PhotoPermissionType::TEMPORARY_READ_IMAGEVIDEO)));
119 permissionTypes.emplace_back(to_string(
120 static_cast<int32_t>(PhotoPermissionType::TEMPORARY_WRITE_IMAGEVIDEO)));
121 permissionTypes.emplace_back(to_string(
122 static_cast<int32_t>(PhotoPermissionType::TEMPORARY_READWRITE_IMAGEVIDEO)));
123 predicatesUnSubscribe.And()->In(AppUriPermissionColumn::PERMISSION_TYPE, permissionTypes);
124 vector<string> columns = { AppUriPermissionColumn::ID };
125 auto resultSet = rdbStore->Query(predicatesUnSubscribe, columns);
126 CHECK_AND_RETURN_RET_LOG(resultSet != nullptr, E_ERR, "Can not query URIPERMISSION");
127
128 int32_t count = 0;
129 auto ret = resultSet->GetRowCount(count);
130 CHECK_AND_RETURN_RET_LOG(ret == NativeRdb::E_OK, E_ERR, "GetRowCount failed ret:%{public}d", ret);
131 return count;
132 }
133
CountHideSensitive(const std::shared_ptr<MediaLibraryRdbStore> rdbStore)134 static int32_t CountHideSensitive(const std::shared_ptr<MediaLibraryRdbStore> rdbStore)
135 {
136 NativeRdb::AbsRdbPredicates predicatesUnSubscribe(AppUriSensitiveColumn::APP_URI_SENSITIVE_TABLE);
137 vector<string> columns = { AppUriPermissionColumn::ID };
138 auto resultSet = rdbStore->Query(predicatesUnSubscribe, columns);
139 CHECK_AND_RETURN_RET_LOG(resultSet != nullptr, E_ERR, "Can not query URIPERMISSION");
140
141 int32_t count = 0;
142 auto ret = resultSet->GetRowCount(count);
143 CHECK_AND_RETURN_RET_LOG(ret == NativeRdb::E_OK, E_ERR, "GetRowCount failed ret:%{public}d", ret);
144 return count;
145 }
146
TryUnSubscribeAppState(const std::shared_ptr<MediaLibraryRdbStore> rdbStore)147 static void TryUnSubscribeAppState(const std::shared_ptr<MediaLibraryRdbStore> rdbStore)
148 {
149 int32_t countPermission = CountTemporaryPermission(rdbStore);
150 int32_t countSensitive = CountHideSensitive(rdbStore);
151 bool cond = (countPermission < 0 || countSensitive < 0);
152 CHECK_AND_PRINT_LOG(!cond, "TryUnSubscribeAppState System exception");
153
154 if (countPermission == 0 && countSensitive == 0) {
155 MedialibraryAppStateObserverManager::GetInstance().UnSubscribeAppState();
156 MEDIA_INFO_LOG("No temporary permission record remains ,UnSubscribeAppState");
157 }
158 }
159
DeleteTemporaryPermission(const std::shared_ptr<MediaLibraryRdbStore> rdbStore,const uint32_t tokenId)160 static int32_t DeleteTemporaryPermission(const std::shared_ptr<MediaLibraryRdbStore> rdbStore, const uint32_t tokenId)
161 {
162 NativeRdb::AbsRdbPredicates predicates(AppUriPermissionColumn::APP_URI_PERMISSION_TABLE);
163 predicates.EqualTo(AppUriPermissionColumn::TARGET_TOKENID, static_cast<int64_t>(tokenId));
164 vector<string> permissionTypes;
165 permissionTypes.emplace_back(to_string(
166 static_cast<int32_t>(PhotoPermissionType::TEMPORARY_READ_IMAGEVIDEO)));
167 permissionTypes.emplace_back(to_string(
168 static_cast<int32_t>(PhotoPermissionType::TEMPORARY_WRITE_IMAGEVIDEO)));
169 permissionTypes.emplace_back(to_string(
170 static_cast<int32_t>(PhotoPermissionType::TEMPORARY_READWRITE_IMAGEVIDEO)));
171 predicates.And()->In(AppUriPermissionColumn::PERMISSION_TYPE, permissionTypes);
172 int32_t deletedRows = -1;
173
174 auto ret = rdbStore->Delete(deletedRows, predicates);
175 bool cond = (ret != NativeRdb::E_OK || deletedRows < 0);
176 CHECK_AND_PRINT_LOG(!cond, "Story Delete db failed, errCode = %{public}d", ret);
177 MEDIA_INFO_LOG("Uripermission Delete retVal: %{public}d, deletedRows: %{public}d", ret, deletedRows);
178
179 return deletedRows;
180 }
181
DeleteHideSensitive(const std::shared_ptr<MediaLibraryRdbStore> rdbStore,const uint32_t tokenId)182 static int32_t DeleteHideSensitive(const std::shared_ptr<MediaLibraryRdbStore> rdbStore, const uint32_t tokenId)
183 {
184 NativeRdb::AbsRdbPredicates predicates(AppUriSensitiveColumn::APP_URI_SENSITIVE_TABLE);
185 predicates.EqualTo(AppUriPermissionColumn::TARGET_TOKENID, static_cast<int64_t>(tokenId));
186 int32_t deletedRows = -1;
187 auto ret = rdbStore->Delete(deletedRows, predicates);
188 bool cond = (ret != NativeRdb::E_OK || deletedRows < 0);
189 CHECK_AND_PRINT_LOG(!cond, "Story Delete db failed, errCode = %{public}d", ret);
190 MEDIA_INFO_LOG("Uripermission Delete retVal: %{public}d, deletedRows: %{public}d", ret, deletedRows);
191
192 return deletedRows;
193 }
194
WaitAndRevoke(int64_t tokenId)195 void MedialibraryAppStateObserver::WaitAndRevoke(int64_t tokenId)
196 {
197 MedialibraryAppStateObserverManager::GetInstance().AddTokenId(tokenId, true);
198 std::this_thread::sleep_for(chrono::milliseconds(WAITFOR_REVOKE));
199 if (!MedialibraryAppStateObserverManager::GetInstance().NeedRevoke(tokenId)) {
200 MEDIA_INFO_LOG("MedialibraryAppStateObserver stop revoke tokenId:%{public}ld", static_cast<long>(tokenId));
201 return;
202 }
203 MEDIA_INFO_LOG("MedialibraryAppStateObserver OnAppStopped, tokenId:%{public}ld", static_cast<long>(tokenId));
204 auto rdbStore = MediaLibraryDataManager::GetInstance()->rdbStore_;
205 CHECK_AND_RETURN_LOG(rdbStore != nullptr, "Uripermission Delete failed, rdbStore is null.");
206
207 int32_t deletedRowsPermission = DeleteTemporaryPermission(rdbStore, tokenId);
208 int32_t deletedRowsSensitive = DeleteHideSensitive(rdbStore, tokenId);
209 MedialibraryAppStateObserverManager::GetInstance().RemoveTokenId(tokenId);
210 TryUnSubscribeAppState(rdbStore);
211 }
212
OnAppStopped(const AppStateData & appStateData)213 void MedialibraryAppStateObserver::OnAppStopped(const AppStateData &appStateData)
214 {
215 auto tokenId = appStateData.accessTokenId;
216 if (!MedialibraryAppStateObserverManager::GetInstance().IsContainTokenId(tokenId)) {
217 return;
218 }
219 MEDIA_INFO_LOG("MedialibraryAppStateObserver TokenId: %{public}ld OnAppStopped, revoke permission",
220 static_cast<long>(tokenId));
221 std::thread revokeThread([this, tokenId]() { this->WaitAndRevoke(tokenId); });
222 revokeThread.detach();
223 }
224
OnAppStarted(const AppStateData & appStateData)225 void MedialibraryAppStateObserver::OnAppStarted(const AppStateData &appStateData)
226 {
227 auto tokenId = appStateData.accessTokenId;
228 if (MedialibraryAppStateObserverManager::GetInstance().IsContainTokenId(tokenId)) {
229 MEDIA_INFO_LOG("MedialibraryAppStateObserver OnAppStarted tokenId: %{public}ld reStart, cancel revoke",
230 static_cast<long>(tokenId));
231 MedialibraryAppStateObserverManager::GetInstance().AddTokenId(tokenId, false);
232 }
233 }
234 } // namespace Media
235 } // namespace OHOS
236