| /* |
| * Copyright (C) 2020 The Android Open Source Project |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| #define LOG_NDEBUG 0 |
| #define LOG_TAG "AActivityManager" |
| #include <utils/Log.h> |
| |
| #include <android/activity_manager.h> |
| #include <android/app/BnProcessObserver.h> |
| #include <android/app/IProcessObserver.h> |
| #include <android/binder_status.h> |
| #include <android/binder_auto_utils.h> |
| #include <android/app/RunningAppProcessInfo.h> |
| #include <binder/ActivityManager.h> |
| |
| #include <mutex> |
| #include <vector> |
| |
| namespace android { |
| namespace activitymanager { |
| |
| // Global instance of ActivityManager, service is obtained only on first use. |
| static ActivityManager gAm; |
| // String tag used with ActivityManager. |
| static const String16& getTag() { |
| static String16 tag("libandroid"); |
| return tag; |
| } |
| |
| struct UidObserver : public BnUidObserver, public virtual IBinder::DeathRecipient { |
| explicit UidObserver(const AActivityManager_onUidImportance& cb, |
| int32_t cutpoint, void* cookie) |
| : mCallback(cb), mImportanceCutpoint(cutpoint), mCookie(cookie), mRegistered(false) {} |
| bool registerSelf(); |
| void unregisterSelf(); |
| |
| // IUidObserver |
| void onUidGone(uid_t uid, bool disabled) override; |
| void onUidActive(uid_t uid) override; |
| void onUidIdle(uid_t uid, bool disabled) override; |
| void onUidStateChanged(uid_t uid, int32_t procState, int64_t procStateSeq, |
| int32_t capability) override; |
| void onUidProcAdjChanged(uid_t uid, int32_t adj) override; |
| |
| // IBinder::DeathRecipient implementation |
| void binderDied(const wp<IBinder>& who) override; |
| |
| static int32_t procStateToImportance(int32_t procState); |
| static int32_t importanceToProcState(int32_t importance); |
| |
| AActivityManager_onUidImportance mCallback; |
| int32_t mImportanceCutpoint; |
| void* mCookie; |
| std::mutex mRegisteredLock; |
| bool mRegistered GUARDED_BY(mRegisteredLock); |
| }; |
| |
| //static |
| int32_t UidObserver::procStateToImportance(int32_t procState) { |
| // TODO: remove this after adding Importance to onUidStateChanged callback. |
| if (procState == ActivityManager::PROCESS_STATE_NONEXISTENT) { |
| return AACTIVITYMANAGER_IMPORTANCE_GONE; |
| } else if (procState >= ActivityManager::PROCESS_STATE_HOME) { |
| return AACTIVITYMANAGER_IMPORTANCE_CACHED; |
| } else if (procState == ActivityManager::PROCESS_STATE_HEAVY_WEIGHT) { |
| return AACTIVITYMANAGER_IMPORTANCE_CANT_SAVE_STATE; |
| } else if (procState >= ActivityManager::PROCESS_STATE_TOP_SLEEPING) { |
| return AACTIVITYMANAGER_IMPORTANCE_TOP_SLEEPING; |
| } else if (procState >= ActivityManager::PROCESS_STATE_SERVICE) { |
| return AACTIVITYMANAGER_IMPORTANCE_SERVICE; |
| } else if (procState >= ActivityManager::PROCESS_STATE_TRANSIENT_BACKGROUND) { |
| return AACTIVITYMANAGER_IMPORTANCE_PERCEPTIBLE; |
| } else if (procState >= ActivityManager::PROCESS_STATE_IMPORTANT_FOREGROUND) { |
| return AACTIVITYMANAGER_IMPORTANCE_VISIBLE; |
| } else if (procState >= ActivityManager::PROCESS_STATE_FOREGROUND_SERVICE) { |
| return AACTIVITYMANAGER_IMPORTANCE_FOREGROUND_SERVICE; |
| } else { |
| return AACTIVITYMANAGER_IMPORTANCE_FOREGROUND; |
| } |
| } |
| |
| //static |
| int32_t UidObserver::importanceToProcState(int32_t importance) { |
| // TODO: remove this after adding Importance to onUidStateChanged callback. |
| if (importance == AACTIVITYMANAGER_IMPORTANCE_GONE) { |
| return ActivityManager::PROCESS_STATE_NONEXISTENT; |
| } else if (importance >= AACTIVITYMANAGER_IMPORTANCE_CACHED) { |
| return ActivityManager::PROCESS_STATE_HOME; |
| } else if (importance >= AACTIVITYMANAGER_IMPORTANCE_CANT_SAVE_STATE) { |
| return ActivityManager::PROCESS_STATE_HEAVY_WEIGHT; |
| } else if (importance >= AACTIVITYMANAGER_IMPORTANCE_TOP_SLEEPING) { |
| return ActivityManager::PROCESS_STATE_TOP_SLEEPING; |
| } else if (importance >= AACTIVITYMANAGER_IMPORTANCE_SERVICE) { |
| return ActivityManager::PROCESS_STATE_SERVICE; |
| } else if (importance >= AACTIVITYMANAGER_IMPORTANCE_PERCEPTIBLE) { |
| return ActivityManager::PROCESS_STATE_TRANSIENT_BACKGROUND; |
| } else if (importance >= AACTIVITYMANAGER_IMPORTANCE_VISIBLE) { |
| return ActivityManager::PROCESS_STATE_IMPORTANT_FOREGROUND; |
| } else if (importance >= AACTIVITYMANAGER_IMPORTANCE_FOREGROUND_SERVICE) { |
| return ActivityManager::PROCESS_STATE_FOREGROUND_SERVICE; |
| } else { |
| return ActivityManager::PROCESS_STATE_TOP; |
| } |
| } |
| |
| |
| void UidObserver::onUidGone(uid_t uid, bool disabled __unused) { |
| std::scoped_lock lock{mRegisteredLock}; |
| |
| if (mRegistered && mCallback) { |
| mCallback(uid, AACTIVITYMANAGER_IMPORTANCE_GONE, mCookie); |
| } |
| } |
| |
| void UidObserver::onUidActive(uid_t uid __unused) {} |
| |
| void UidObserver::onUidIdle(uid_t uid __unused, bool disabled __unused) {} |
| |
| void UidObserver::onUidProcAdjChanged(uid_t uid __unused, int32_t adj __unused) {} |
| |
| void UidObserver::onUidStateChanged(uid_t uid, int32_t procState, |
| int64_t procStateSeq __unused, |
| int32_t capability __unused) { |
| std::scoped_lock lock{mRegisteredLock}; |
| |
| if (mRegistered && mCallback) { |
| mCallback(uid, procStateToImportance(procState), mCookie); |
| } |
| } |
| |
| void UidObserver::binderDied(const wp<IBinder>& /*who*/) { |
| // ActivityManager is dead, try to re-register. |
| { |
| std::scoped_lock lock{mRegisteredLock}; |
| // If client already unregistered, don't try to re-register. |
| if (!mRegistered) { |
| return; |
| } |
| // Clear mRegistered to re-register. |
| mRegistered = false; |
| } |
| registerSelf(); |
| } |
| |
| bool UidObserver::registerSelf() { |
| std::scoped_lock lock{mRegisteredLock}; |
| if (mRegistered) { |
| return true; |
| } |
| |
| status_t res = gAm.linkToDeath(this); |
| if (res != OK) { |
| ALOGE("UidObserver: Failed to linkToDeath with ActivityManager (err %d)", res); |
| return false; |
| } |
| |
| // TODO: it seems only way to get all changes is to set cutoff to PROCESS_STATE_UNKNOWN. |
| // But there is no equivalent of PROCESS_STATE_UNKNOWN in the UidImportance. |
| // If mImportanceCutpoint is < 0, use PROCESS_STATE_UNKNOWN instead. |
| res = gAm.registerUidObserver( |
| this, |
| ActivityManager::UID_OBSERVER_GONE | ActivityManager::UID_OBSERVER_PROCSTATE, |
| (mImportanceCutpoint < 0) ? ActivityManager::PROCESS_STATE_UNKNOWN |
| : importanceToProcState(mImportanceCutpoint), |
| getTag()); |
| if (res != OK) { |
| ALOGE("UidObserver: Failed to register with ActivityManager (err %d)", res); |
| gAm.unlinkToDeath(this); |
| return false; |
| } |
| |
| mRegistered = true; |
| ALOGV("UidObserver: Registered with ActivityManager"); |
| return true; |
| } |
| |
| void UidObserver::unregisterSelf() { |
| std::scoped_lock lock{mRegisteredLock}; |
| |
| if (mRegistered) { |
| gAm.unregisterUidObserver(this); |
| gAm.unlinkToDeath(this); |
| mRegistered = false; |
| } |
| |
| ALOGV("UidObserver: Unregistered with ActivityManager"); |
| } |
| |
| class ProcessObserver : public app::BnProcessObserver { |
| public: |
| explicit ProcessObserver(void* cookie) |
| : mOnProcessStarted(nullptr), |
| mOnForegroundActivitiesChanged(nullptr), |
| mOnForegroundServicesChanged(nullptr), |
| mOnProcessDied(nullptr), |
| mCookie(cookie) {} |
| |
| void setOnProcessStarted(AActivityManager_onProcessStarted cb) { mOnProcessStarted = cb; } |
| void setOnForegroundActivitiesChanged(AActivityManager_onForegroundActivitiesChanged cb) { |
| mOnForegroundActivitiesChanged = cb; |
| } |
| void setOnForegroundServicesChanged(AActivityManager_onForegroundServicesChanged cb) { |
| mOnForegroundServicesChanged = cb; |
| } |
| void setOnProcessDied(AActivityManager_onProcessDied cb) { mOnProcessDied = cb; } |
| |
| bool hasCallbacks() const { |
| return mOnProcessStarted || mOnForegroundActivitiesChanged || |
| mOnForegroundServicesChanged || mOnProcessDied; |
| } |
| |
| binder::Status onProcessStarted(int pid, int processUid, int packageUid, |
| const std::string& packageName, |
| const std::string& processName) override { |
| if (mOnProcessStarted) { |
| mOnProcessStarted(pid, processUid, packageUid, packageName.c_str(), |
| processName.c_str(), mCookie); |
| } |
| return binder::Status::ok(); |
| } |
| |
| binder::Status onForegroundActivitiesChanged(int pid, int uid, |
| bool foregroundActivities) override { |
| if (mOnForegroundActivitiesChanged) { |
| const AActivityManager_ForegroundActivitiesState state = |
| foregroundActivities |
| ? AACTIVITYMANAGER_HAS_FOREGROUND_ACTIVITIES |
| : AACTIVITYMANAGER_NO_FOREGROUND_ACTIVITIES; |
| mOnForegroundActivitiesChanged(pid, uid, state, mCookie); |
| } |
| return binder::Status::ok(); |
| } |
| |
| binder::Status onForegroundServicesChanged(int pid, int uid, int32_t serviceTypes) override { |
| if (mOnForegroundServicesChanged) { |
| mOnForegroundServicesChanged(pid, uid, serviceTypes, mCookie); |
| } |
| return binder::Status::ok(); |
| } |
| |
| binder::Status onProcessDied(int pid, int uid) override { |
| if (mOnProcessDied) { |
| mOnProcessDied(pid, uid, mCookie); |
| } |
| return binder::Status::ok(); |
| } |
| |
| private: |
| AActivityManager_onProcessStarted mOnProcessStarted; |
| AActivityManager_onForegroundActivitiesChanged mOnForegroundActivitiesChanged; |
| AActivityManager_onForegroundServicesChanged mOnForegroundServicesChanged; |
| AActivityManager_onProcessDied mOnProcessDied; |
| void* mCookie; |
| }; |
| |
| } // activitymanager |
| } // android |
| |
| using namespace android; |
| using namespace activitymanager; |
| |
| struct AActivityManager_UidImportanceListener : public UidObserver { |
| }; |
| |
| AActivityManager_UidImportanceListener* AActivityManager_addUidImportanceListener( |
| AActivityManager_onUidImportance onUidImportance, int32_t importanceCutpoint, void* cookie) { |
| sp<UidObserver> observer(new UidObserver(onUidImportance, importanceCutpoint, cookie)); |
| if (observer == nullptr || !observer->registerSelf()) { |
| return nullptr; |
| } |
| observer->incStrong((void *)AActivityManager_addUidImportanceListener); |
| return static_cast<AActivityManager_UidImportanceListener*>(observer.get()); |
| } |
| |
| void AActivityManager_removeUidImportanceListener( |
| AActivityManager_UidImportanceListener* listener) { |
| if (listener != nullptr) { |
| UidObserver* observer = static_cast<UidObserver*>(listener); |
| observer->unregisterSelf(); |
| observer->decStrong((void *)AActivityManager_addUidImportanceListener); |
| } |
| } |
| |
| struct AActivityManager_ProcessObserver { |
| sp<ProcessObserver> observer; |
| bool registered = false; |
| }; |
| |
| AActivityManager_ProcessObserver* AActivityManager_createProcessObserver(void* cookie) { |
| auto handle = new AActivityManager_ProcessObserver(); |
| if (!handle) { |
| return nullptr; |
| } |
| handle->observer = sp<ProcessObserver>::make(cookie); |
| if (handle->observer == nullptr) { |
| delete handle; |
| return nullptr; |
| } |
| return handle; |
| } |
| |
| void AActivityManager_destroyProcessObserver(AActivityManager_ProcessObserver* observer) { |
| if (observer == nullptr) { |
| return; |
| } |
| if (observer->registered) { |
| gAm.unregisterProcessObserver(observer->observer); |
| } |
| delete observer; |
| } |
| |
| void AActivityManager_ProcessObserver_setOnProcessStarted( |
| AActivityManager_ProcessObserver* observer, AActivityManager_onProcessStarted callback) { |
| if (observer && observer->observer) { |
| observer->observer->setOnProcessStarted(callback); |
| } |
| } |
| |
| void AActivityManager_ProcessObserver_setOnForegroundActivitiesChanged( |
| AActivityManager_ProcessObserver* observer, |
| AActivityManager_onForegroundActivitiesChanged callback) { |
| if (observer && observer->observer) { |
| observer->observer->setOnForegroundActivitiesChanged(callback); |
| } |
| } |
| |
| void AActivityManager_ProcessObserver_setOnForegroundServicesChanged( |
| AActivityManager_ProcessObserver* observer, |
| AActivityManager_onForegroundServicesChanged callback) { |
| if (observer && observer->observer) { |
| observer->observer->setOnForegroundServicesChanged(callback); |
| } |
| } |
| |
| void AActivityManager_ProcessObserver_setOnProcessDied( |
| AActivityManager_ProcessObserver* observer, AActivityManager_onProcessDied callback) { |
| if (observer && observer->observer) { |
| observer->observer->setOnProcessDied(callback); |
| } |
| } |
| |
| binder_status_t AActivityManager_registerProcessObserver( |
| AActivityManager_ProcessObserver* observer) { |
| if (observer == nullptr || observer->observer == nullptr) { |
| return STATUS_BAD_VALUE; |
| } |
| if (observer->registered) { |
| return STATUS_INVALID_OPERATION; |
| } |
| if (!observer->observer->hasCallbacks()) { |
| return STATUS_BAD_VALUE; |
| } |
| |
| status_t status = gAm.registerProcessObserver(observer->observer); |
| if (status != OK) { |
| ALOGE("ProcessObserver: Failed to register with ActivityManager (err %d)", status); |
| return ndk::ScopedAStatus::fromStatus(status).getStatus(); |
| } |
| |
| observer->registered = true; |
| return STATUS_OK; |
| } |
| |
| void AActivityManager_unregisterProcessObserver(AActivityManager_ProcessObserver* observer) { |
| if (observer == nullptr || !observer->registered) { |
| return; |
| } |
| gAm.unregisterProcessObserver(observer->observer); |
| observer->registered = false; |
| } |
| |
| struct ARunningAppProcessInfo { |
| pid_t pid; |
| uid_t uid; |
| std::string processName; |
| std::vector<std::string> pkgList; |
| int32_t importance; |
| std::vector<const char*> pkgListCStr; |
| }; |
| |
| struct ARunningAppProcessInfoList { |
| std::vector<ARunningAppProcessInfo> list; |
| }; |
| |
| binder_status_t AActivityManager_getRunningAppProcesses( |
| ARunningAppProcessInfoList** outProcessInfoList) { |
| if (outProcessInfoList == nullptr) { |
| return STATUS_BAD_VALUE; |
| } |
| |
| std::vector<app::RunningAppProcessInfo> processes; |
| status_t status = gAm.getRunningAppProcesses(&processes); |
| if (status != OK) { |
| return ndk::ScopedAStatus::fromStatus(status).getStatus(); |
| } |
| |
| auto* list = new ARunningAppProcessInfoList(); |
| list->list.reserve(processes.size()); |
| |
| for (const auto& p : processes) { |
| ARunningAppProcessInfo info; |
| info.pid = p.pid; |
| info.uid = p.uid; |
| info.processName = p.processName; |
| if (p.pkgList.has_value()) { |
| for (const auto& pkg : p.pkgList.value()) { |
| if (pkg.has_value()) { |
| info.pkgList.push_back(pkg.value()); |
| } |
| } |
| } |
| info.importance = p.importance; |
| |
| info.pkgListCStr.reserve(info.pkgList.size()); |
| for (const auto& pkg : info.pkgList) { |
| info.pkgListCStr.push_back(pkg.c_str()); |
| } |
| list->list.emplace_back(std::move(info)); |
| } |
| |
| *outProcessInfoList = list; |
| return STATUS_OK; |
| } |
| |
| void AActivityManager_RunningAppProcessInfoList_destroy(const ARunningAppProcessInfoList* list) { |
| delete list; |
| } |
| |
| size_t AActivityManager_RunningAppProcessInfoList_getSize(const ARunningAppProcessInfoList* list) { |
| return list->list.size(); |
| } |
| |
| const ARunningAppProcessInfo* AActivityManager_RunningAppProcessInfoList_get( |
| const ARunningAppProcessInfoList* list, size_t index) { |
| if (index >= list->list.size()) { |
| return nullptr; |
| } |
| return &list->list[index]; |
| } |
| |
| bool AActivityManager_isUidActive(uid_t uid) { |
| return gAm.isUidActive(uid, getTag()); |
| } |
| |
| int32_t AActivityManager_getUidImportance(uid_t uid) { |
| return UidObserver::procStateToImportance(gAm.getUidProcessState(uid, getTag())); |
| } |
| |
| pid_t ARunningAppProcessInfo_getPid(const ARunningAppProcessInfo* info) { return info->pid; } |
| |
| uid_t ARunningAppProcessInfo_getUid(const ARunningAppProcessInfo* info) { return info->uid; } |
| |
| const char* ARunningAppProcessInfo_getProcessName(const ARunningAppProcessInfo* info) { |
| return info->processName.c_str(); |
| } |
| |
| const char* const* ARunningAppProcessInfo_getPackageList(const ARunningAppProcessInfo* info, |
| size_t* outNumPackages) { |
| *outNumPackages = info->pkgListCStr.size(); |
| if (info->pkgListCStr.empty()) { |
| return nullptr; |
| } |
| return info->pkgListCStr.data(); |
| } |
| |
| int32_t ARunningAppProcessInfo_getImportance(const ARunningAppProcessInfo* info) { |
| return info->importance; |
| } |