Merge "adpf: Use one client token per process for all hint sessions" into tm-dev

This commit is contained in:
TreeHugger Robot
2022-03-02 00:38:23 +00:00
committed by Android (Google) Code Review
2 changed files with 47 additions and 17 deletions

View File

@@ -48,6 +48,7 @@ private:
static APerformanceHintManager* create(sp<IHintManager> iHintManager); static APerformanceHintManager* create(sp<IHintManager> iHintManager);
sp<IHintManager> mHintManager; sp<IHintManager> mHintManager;
const sp<IBinder> mToken = sp<BBinder>::make();
const int64_t mPreferredRateNanos; const int64_t mPreferredRateNanos;
}; };
@@ -119,11 +120,10 @@ APerformanceHintManager* APerformanceHintManager::create(sp<IHintManager> manage
APerformanceHintSession* APerformanceHintManager::createSession( APerformanceHintSession* APerformanceHintManager::createSession(
const int32_t* threadIds, size_t size, int64_t initialTargetWorkDurationNanos) { const int32_t* threadIds, size_t size, int64_t initialTargetWorkDurationNanos) {
sp<IBinder> token = sp<BBinder>::make();
std::vector<int32_t> tids(threadIds, threadIds + size); std::vector<int32_t> tids(threadIds, threadIds + size);
sp<IHintSession> session; sp<IHintSession> session;
binder::Status ret = binder::Status ret =
mHintManager->createHintSession(token, tids, initialTargetWorkDurationNanos, &session); mHintManager->createHintSession(mToken, tids, initialTargetWorkDurationNanos, &session);
if (!ret.isOk() || !session) { if (!ret.isOk() || !session) {
return nullptr; return nullptr;
} }

View File

@@ -27,6 +27,7 @@ import android.os.IHintSession;
import android.os.Process; import android.os.Process;
import android.os.RemoteException; import android.os.RemoteException;
import android.util.ArrayMap; import android.util.ArrayMap;
import android.util.ArraySet;
import android.util.SparseArray; import android.util.SparseArray;
import com.android.internal.annotations.GuardedBy; import com.android.internal.annotations.GuardedBy;
@@ -51,8 +52,13 @@ public final class HintManagerService extends SystemService {
private static final boolean DEBUG = false; private static final boolean DEBUG = false;
@VisibleForTesting final long mHintSessionPreferredRate; @VisibleForTesting final long mHintSessionPreferredRate;
// Multi-levle map storing all active AppHintSessions.
// First level is keyed by the UID of the client process creating the session.
// Second level is keyed by an IBinder passed from client process. This is used to observe
// when the process exits. The client generally uses the same IBinder object across multiple
// sessions, so the value is a set of AppHintSessions.
@GuardedBy("mLock") @GuardedBy("mLock")
private final ArrayMap<Integer, ArrayMap<IBinder, AppHintSession>> mActiveSessions; private final ArrayMap<Integer, ArrayMap<IBinder, ArraySet<AppHintSession>>> mActiveSessions;
/** Lock to protect HAL handles and listen list. */ /** Lock to protect HAL handles and listen list. */
private final Object mLock = new Object(); private final Object mLock = new Object();
@@ -201,13 +207,16 @@ public final class HintManagerService extends SystemService {
public void onUidGone(int uid, boolean disabled) { public void onUidGone(int uid, boolean disabled) {
FgThread.getHandler().post(() -> { FgThread.getHandler().post(() -> {
synchronized (mLock) { synchronized (mLock) {
ArrayMap<IBinder, AppHintSession> tokenMap = mActiveSessions.get(uid); ArrayMap<IBinder, ArraySet<AppHintSession>> tokenMap = mActiveSessions.get(uid);
if (tokenMap == null) { if (tokenMap == null) {
return; return;
} }
for (int i = tokenMap.size() - 1; i >= 0; i--) { for (int i = tokenMap.size() - 1; i >= 0; i--) {
// Will remove the session from tokenMap // Will remove the session from tokenMap
tokenMap.valueAt(i).close(); ArraySet<AppHintSession> sessionSet = tokenMap.valueAt(i);
for (int j = sessionSet.size() - 1; j >= 0; j--) {
sessionSet.valueAt(j).close();
}
} }
mProcStatesCache.delete(uid); mProcStatesCache.delete(uid);
} }
@@ -231,12 +240,14 @@ public final class HintManagerService extends SystemService {
FgThread.getHandler().post(() -> { FgThread.getHandler().post(() -> {
synchronized (mLock) { synchronized (mLock) {
mProcStatesCache.put(uid, procState); mProcStatesCache.put(uid, procState);
ArrayMap<IBinder, AppHintSession> tokenMap = mActiveSessions.get(uid); ArrayMap<IBinder, ArraySet<AppHintSession>> tokenMap = mActiveSessions.get(uid);
if (tokenMap == null) { if (tokenMap == null) {
return; return;
} }
for (AppHintSession s : tokenMap.values()) { for (ArraySet<AppHintSession> sessionSet : tokenMap.values()) {
s.onProcStateChanged(); for (AppHintSession s : sessionSet) {
s.onProcStateChanged();
}
} }
} }
}); });
@@ -305,17 +316,25 @@ public final class HintManagerService extends SystemService {
long halSessionPtr = mNativeWrapper.halCreateHintSession(callingTgid, callingUid, long halSessionPtr = mNativeWrapper.halCreateHintSession(callingTgid, callingUid,
tids, durationNanos); tids, durationNanos);
if (halSessionPtr == 0) return null; if (halSessionPtr == 0) {
return null;
}
AppHintSession hs = new AppHintSession(callingUid, callingTgid, tids, token, AppHintSession hs = new AppHintSession(callingUid, callingTgid, tids, token,
halSessionPtr, durationNanos); halSessionPtr, durationNanos);
synchronized (mLock) { synchronized (mLock) {
ArrayMap<IBinder, AppHintSession> tokenMap = mActiveSessions.get(callingUid); ArrayMap<IBinder, ArraySet<AppHintSession>> tokenMap =
mActiveSessions.get(callingUid);
if (tokenMap == null) { if (tokenMap == null) {
tokenMap = new ArrayMap<>(1); tokenMap = new ArrayMap<>(1);
mActiveSessions.put(callingUid, tokenMap); mActiveSessions.put(callingUid, tokenMap);
} }
tokenMap.put(token, hs); ArraySet<AppHintSession> sessionSet = tokenMap.get(token);
if (sessionSet == null) {
sessionSet = new ArraySet<>(1);
tokenMap.put(token, sessionSet);
}
sessionSet.add(hs);
return hs; return hs;
} }
} finally { } finally {
@@ -339,10 +358,14 @@ public final class HintManagerService extends SystemService {
pw.println("Active Sessions:"); pw.println("Active Sessions:");
for (int i = 0; i < mActiveSessions.size(); i++) { for (int i = 0; i < mActiveSessions.size(); i++) {
pw.println("Uid " + mActiveSessions.keyAt(i).toString() + ":"); pw.println("Uid " + mActiveSessions.keyAt(i).toString() + ":");
ArrayMap<IBinder, AppHintSession> tokenMap = mActiveSessions.valueAt(i); ArrayMap<IBinder, ArraySet<AppHintSession>> tokenMap =
mActiveSessions.valueAt(i);
for (int j = 0; j < tokenMap.size(); j++) { for (int j = 0; j < tokenMap.size(); j++) {
pw.println(" Session " + j + ":"); ArraySet<AppHintSession> sessionSet = tokenMap.valueAt(j);
tokenMap.valueAt(j).dump(pw, " "); for (int k = 0; k < sessionSet.size(); ++k) {
pw.println(" Session:");
sessionSet.valueAt(k).dump(pw, " ");
}
} }
} }
} }
@@ -432,11 +455,18 @@ public final class HintManagerService extends SystemService {
mNativeWrapper.halCloseHintSession(mHalSessionPtr); mNativeWrapper.halCloseHintSession(mHalSessionPtr);
mHalSessionPtr = 0; mHalSessionPtr = 0;
mToken.unlinkToDeath(this, 0); mToken.unlinkToDeath(this, 0);
ArrayMap<IBinder, AppHintSession> tokenMap = mActiveSessions.get(mUid); ArrayMap<IBinder, ArraySet<AppHintSession>> tokenMap = mActiveSessions.get(mUid);
if (tokenMap == null) { if (tokenMap == null) {
Slogf.w(TAG, "UID %d is note present in active session map", mUid); Slogf.w(TAG, "UID %d is not present in active session map", mUid);
return;
} }
tokenMap.remove(mToken); ArraySet<AppHintSession> sessionSet = tokenMap.get(mToken);
if (sessionSet == null) {
Slogf.w(TAG, "Token %s is not present in token map", mToken.toString());
return;
}
sessionSet.remove(this);
if (sessionSet.isEmpty()) tokenMap.remove(mToken);
if (tokenMap.isEmpty()) mActiveSessions.remove(mUid); if (tokenMap.isEmpty()) mActiveSessions.remove(mUid);
} }
} }