Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 8af87925 authored by Chong Zhang's avatar Chong Zhang
Browse files

Add ActivityManager UidImportanceListener to libandroid

Add UidImportanceListener methods to libandroid for native apex use.

bug: 172942349
bug: 159172726
bug: 146507383

test: updated mediatranscoding's UidPolicy locally to use the new api,
and passed mediatranscodingservice unit tests.

Change-Id: I7ca76f057a83b5bcd634deb2408784d7b93e46fc
parent 5cdfff40
Loading
Loading
Loading
Loading
+5 −0
Original line number Diff line number Diff line
@@ -36,6 +36,7 @@ cc_library_shared {
    defaults: ["libandroid_defaults"],

    srcs: [
        "activity_manager.cpp",
        "asset_manager.cpp",
        "choreographer.cpp",
        "configuration.cpp",
@@ -95,6 +96,10 @@ cc_library_shared {

    include_dirs: ["bionic/libc/dns/include"],

    local_include_dirs: [ "include_platform", ],

    export_include_dirs: [ "include_platform", ],

    version_script: "libandroid.map.txt",
    stubs: {
        symbol_file: "libandroid.map.txt",
+226 −0
Original line number Diff line number Diff line
/*
 * 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;

    // 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::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()));
}
+176 −0
Original line number Diff line number Diff line
/*
 * 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.
 */

#ifndef __AACTIVITYMANAGER_H__
#define __AACTIVITYMANAGER_H__

#include <sys/cdefs.h>
#include <sys/types.h>

__BEGIN_DECLS

struct AActivityManager_UidImportanceListener;
typedef struct AActivityManager_UidImportanceListener AActivityManager_UidImportanceListener;

/**
 * Callback interface when Uid Importance has changed for a uid.
 *
 * This callback will be called on an arbitrary thread. Calls to a given listener will be
 * serialized.
 *
 * @param uid the uid for which the importance has changed.
 * @param uidImportance the new uidImportance for the uid.
 * @cookie the same cookie when the UidImportanceListener was added.
 *
 * Introduced in API 31.
 */
typedef void (*AActivityManager_onUidImportance)(uid_t uid, int32_t uidImportance, void* cookie);

/**
 * ActivityManager Uid Importance constants.
 *
 * Introduced in API 31.
 */
enum {
    /**
     * Constant for Uid Importance: This process is running the
     * foreground UI; that is, it is the thing currently at the top of the screen
     * that the user is interacting with.
     */
    AACTIVITYMANAGER_IMPORTANCE_FOREGROUND = 100,

    /**
     * Constant for Uid Importance: This process is running a foreground
     * service, for example to perform music playback even while the user is
     * not immediately in the app.  This generally indicates that the process
     * is doing something the user actively cares about.
     */
    AACTIVITYMANAGER_IMPORTANCE_FOREGROUND_SERVICE = 125,

    /**
     * Constant for Uid Importance: This process is running something
     * that is actively visible to the user, though not in the immediate
     * foreground.  This may be running a window that is behind the current
     * foreground (so paused and with its state saved, not interacting with
     * the user, but visible to them to some degree); it may also be running
     * other services under the system's control that it inconsiders important.
     */
    AACTIVITYMANAGER_IMPORTANCE_VISIBLE = 200,

    /**
     * Constant for Uid Importance: This process is not something the user
     * is directly aware of, but is otherwise perceptible to them to some degree.
     */
    AACTIVITYMANAGER_IMPORTANCE_PERCEPTIBLE = 230,

    /**
     * Constant for Uid Importance: This process contains services
     * that should remain running.  These are background services apps have
     * started, not something the user is aware of, so they may be killed by
     * the system relatively freely (though it is generally desired that they
     * stay running as long as they want to).
     */
    AACTIVITYMANAGER_IMPORTANCE_SERVICE = 300,

    /**
     * Constant for Uid Importance: This process is running the foreground
     * UI, but the device is asleep so it is not visible to the user.  Though the
     * system will try hard to keep its process from being killed, in all other
     * ways we consider it a kind of cached process, with the limitations that go
     * along with that state: network access, running background services, etc.
     */
    AACTIVITYMANAGER_IMPORTANCE_TOP_SLEEPING = 325,

    /**
     * Constant for Uid Importance: This process is running an
     * application that can not save its state, and thus can't be killed
     * while in the background.  This will be used with apps that have
     * {@link android.R.attr#cantSaveState} set on their application tag.
     */
    AACTIVITYMANAGER_IMPORTANCE_CANT_SAVE_STATE = 350,

    /**
     * Constant for Uid Importance: This process process contains
     * cached code that is expendable, not actively running any app components
     * we care about.
     */
    AACTIVITYMANAGER_IMPORTANCE_CACHED = 400,

    /**
     * Constant for Uid Importance: This process does not exist.
     */
    AACTIVITYMANAGER_IMPORTANCE_GONE = 1000,
};

#if __ANDROID_API__ >= 31

/**
 * Adds a UidImportanceListener to the ActivityManager.
 *
 * This API requires android.Manifest.permission.PACKAGE_USAGE_STATS permission.
 *
 * @param onUidImportance the listener callback that will receive change reports.
 *
 * @param importanceCutpoint the level of importance in which the caller is interested
 * in differences. For example, if AACTIVITYMANAGER_IMPORTANCE_PERCEPTIBLE is used
 * here, you will receive a call each time a uid's importance transitions between being
 * <= AACTIVITYMANAGER_IMPORTANCE_PERCEPTIBLE and > AACTIVITYMANAGER_IMPORTANCE_PERCEPTIBLE.
 *
 * @param cookie a cookie that will be passed back to the listener callback.
 *
 * @return an opaque pointer of AActivityManager_UidImportanceListener, or nullptr
 * upon failure. Upon success, the returned AActivityManager_UidImportanceListener pointer
 * must be removed and released through AActivityManager_removeUidImportanceListener.
 */
AActivityManager_UidImportanceListener* AActivityManager_addUidImportanceListener(
        AActivityManager_onUidImportance onUidImportance,
        int32_t importanceCutpoint,
        void* cookie) __INTRODUCED_IN(31);

/**
 * Removes a UidImportanceListener that was added with AActivityManager_addUidImportanceListener.
 *
 * When this returns, it's guaranteed the listener callback will no longer be invoked.
 *
 * @param listener the UidImportanceListener to be removed.
 */
void AActivityManager_removeUidImportanceListener(
        AActivityManager_UidImportanceListener* listener) __INTRODUCED_IN(31);

/**
 * Queries if a uid is currently active.
 *
 * This API requires android.Manifest.permission.PACKAGE_USAGE_STATS permission.
 *
 * @return true if the uid is active, false otherwise.
 */
bool AActivityManager_isUidActive(uid_t uid) __INTRODUCED_IN(31);

/**
 * Queries the current Uid Importance value of a uid.
 *
 * This API requires android.Manifest.permission.PACKAGE_USAGE_STATS permission.
 *
 * @param uid the uid for which the importance value is queried.
 * @return the current uid importance value for uid.
 */
int32_t AActivityManager_getUidImportance(uid_t uid) __INTRODUCED_IN(31);

#endif // __ANDROID_API__ >= 31

__END_DECLS

#endif  // __AACTIVITYMANAGER_H__
+4 −0
Original line number Diff line number Diff line
LIBANDROID {
  global:
    AActivityManager_addUidImportanceListener; # apex # introduced=31
    AActivityManager_removeUidImportanceListener; # apex # introduced=31
    AActivityManager_isUidActive; # apex # introduced=31
    AActivityManager_getUidImportance; # apex # introduced=31
    AAssetDir_close;
    AAssetDir_getNextFileName;
    AAssetDir_rewind;