|  | /* | 
|  | * 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 <binder/ActivityManager.h> | 
|  |  | 
|  | 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"); | 
|  | } | 
|  |  | 
|  | } // 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); | 
|  | } | 
|  | } | 
|  |  | 
|  | 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())); | 
|  | } | 
|  |  |