/* * 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 #include #include 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; // IBinder::DeathRecipient implementation void binderDied(const wp& 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::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& /*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 observer(new UidObserver(onUidImportance, importanceCutpoint, cookie)); if (observer == nullptr || !observer->registerSelf()) { return nullptr; } observer->incStrong((void *)AActivityManager_addUidImportanceListener); return static_cast(observer.get()); } void AActivityManager_removeUidImportanceListener( AActivityManager_UidImportanceListener* listener) { if (listener != nullptr) { UidObserver* observer = static_cast(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())); }