Merge "Don't call ActivityManagerService on main thread" into qt-dev
This commit is contained in:
@@ -190,9 +190,7 @@ public class AttentionManagerService extends SystemService {
|
|||||||
|
|
||||||
final UserState userState = getOrCreateCurrentUserStateLocked();
|
final UserState userState = getOrCreateCurrentUserStateLocked();
|
||||||
// lazily start the service, which should be very lightweight to start
|
// lazily start the service, which should be very lightweight to start
|
||||||
if (!userState.bindLocked()) {
|
userState.bindLocked();
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// throttle frequent requests
|
// throttle frequent requests
|
||||||
final AttentionCheckCache cache = userState.mAttentionCheckCache;
|
final AttentionCheckCache cache = userState.mAttentionCheckCache;
|
||||||
@@ -310,7 +308,7 @@ public class AttentionManagerService extends SystemService {
|
|||||||
protected UserState getOrCreateUserStateLocked(int userId) {
|
protected UserState getOrCreateUserStateLocked(int userId) {
|
||||||
UserState result = mUserStates.get(userId);
|
UserState result = mUserStates.get(userId);
|
||||||
if (result == null) {
|
if (result == null) {
|
||||||
result = new UserState(userId, mContext, mLock, mComponentName);
|
result = new UserState(userId, mContext, mLock, mAttentionHandler, mComponentName);
|
||||||
mUserStates.put(userId, result);
|
mUserStates.put(userId, result);
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
@@ -456,31 +454,33 @@ public class AttentionManagerService extends SystemService {
|
|||||||
|
|
||||||
@VisibleForTesting
|
@VisibleForTesting
|
||||||
protected static class UserState {
|
protected static class UserState {
|
||||||
final ComponentName mComponentName;
|
private final ComponentName mComponentName;
|
||||||
final AttentionServiceConnection mConnection = new AttentionServiceConnection();
|
private final AttentionServiceConnection mConnection = new AttentionServiceConnection();
|
||||||
|
|
||||||
@GuardedBy("mLock")
|
@GuardedBy("mLock")
|
||||||
IAttentionService mService;
|
IAttentionService mService;
|
||||||
@GuardedBy("mLock")
|
@GuardedBy("mLock")
|
||||||
boolean mBinding;
|
|
||||||
@GuardedBy("mLock")
|
|
||||||
AttentionCheck mCurrentAttentionCheck;
|
AttentionCheck mCurrentAttentionCheck;
|
||||||
@GuardedBy("mLock")
|
@GuardedBy("mLock")
|
||||||
AttentionCheckCache mAttentionCheckCache;
|
AttentionCheckCache mAttentionCheckCache;
|
||||||
|
@GuardedBy("mLock")
|
||||||
|
private boolean mBinding;
|
||||||
|
|
||||||
@UserIdInt
|
@UserIdInt
|
||||||
final int mUserId;
|
private final int mUserId;
|
||||||
final Context mContext;
|
private final Context mContext;
|
||||||
final Object mLock;
|
private final Object mLock;
|
||||||
|
private final Handler mAttentionHandler;
|
||||||
|
|
||||||
UserState(int userId, Context context, Object lock, ComponentName componentName) {
|
UserState(int userId, Context context, Object lock, Handler handler,
|
||||||
|
ComponentName componentName) {
|
||||||
mUserId = userId;
|
mUserId = userId;
|
||||||
mContext = Preconditions.checkNotNull(context);
|
mContext = Preconditions.checkNotNull(context);
|
||||||
mLock = Preconditions.checkNotNull(lock);
|
mLock = Preconditions.checkNotNull(lock);
|
||||||
mComponentName = Preconditions.checkNotNull(componentName);
|
mComponentName = Preconditions.checkNotNull(componentName);
|
||||||
|
mAttentionHandler = handler;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@GuardedBy("mLock")
|
@GuardedBy("mLock")
|
||||||
private void handlePendingCallbackLocked() {
|
private void handlePendingCallbackLocked() {
|
||||||
if (!mCurrentAttentionCheck.mIsDispatched) {
|
if (!mCurrentAttentionCheck.mIsDispatched) {
|
||||||
@@ -499,26 +499,25 @@ public class AttentionManagerService extends SystemService {
|
|||||||
|
|
||||||
/** Binds to the system's AttentionService which provides an actual implementation. */
|
/** Binds to the system's AttentionService which provides an actual implementation. */
|
||||||
@GuardedBy("mLock")
|
@GuardedBy("mLock")
|
||||||
private boolean bindLocked() {
|
private void bindLocked() {
|
||||||
// No need to bind if service is binding or has already been bound.
|
// No need to bind if service is binding or has already been bound.
|
||||||
if (mBinding || mService != null) {
|
if (mBinding || mService != null) {
|
||||||
return true;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
final boolean willBind;
|
mBinding = true;
|
||||||
final long identity = Binder.clearCallingIdentity();
|
// mContext.bindServiceAsUser() calls into ActivityManagerService which it may already
|
||||||
|
// hold the lock and had called into PowerManagerService, which holds a lock.
|
||||||
try {
|
// That would create a deadlock. To solve that, putting it on a handler.
|
||||||
final Intent mServiceIntent = new Intent(
|
mAttentionHandler.post(() -> {
|
||||||
|
final Intent serviceIntent = new Intent(
|
||||||
AttentionService.SERVICE_INTERFACE).setComponent(
|
AttentionService.SERVICE_INTERFACE).setComponent(
|
||||||
mComponentName);
|
mComponentName);
|
||||||
willBind = mContext.bindServiceAsUser(mServiceIntent, mConnection,
|
// Note: no reason to clear the calling identity, we won't have one in a handler.
|
||||||
|
mContext.bindServiceAsUser(serviceIntent, mConnection,
|
||||||
Context.BIND_AUTO_CREATE, UserHandle.CURRENT);
|
Context.BIND_AUTO_CREATE, UserHandle.CURRENT);
|
||||||
mBinding = willBind;
|
|
||||||
} finally {
|
});
|
||||||
Binder.restoreCallingIdentity(identity);
|
|
||||||
}
|
|
||||||
return willBind;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void dump(IndentingPrintWriter pw) {
|
private void dump(IndentingPrintWriter pw) {
|
||||||
@@ -587,6 +586,7 @@ public class AttentionManagerService extends SystemService {
|
|||||||
super(Looper.myLooper());
|
super(Looper.myLooper());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public void handleMessage(Message msg) {
|
public void handleMessage(Message msg) {
|
||||||
switch (msg.what) {
|
switch (msg.what) {
|
||||||
// Do not occupy resources when not in use - unbind proactively.
|
// Do not occupy resources when not in use - unbind proactively.
|
||||||
@@ -651,7 +651,12 @@ public class AttentionManagerService extends SystemService {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
mContext.unbindService(userState.mConnection);
|
mAttentionHandler.post(() -> mContext.unbindService(userState.mConnection));
|
||||||
|
// Note: this will set mBinding to false even though it could still be trying to bind
|
||||||
|
// (i.e. the runnable was posted in bindLocked but then cancelAndUnbindLocked was
|
||||||
|
// called before it's run yet). This is a safe state at the moment,
|
||||||
|
// since it will eventually, but feels like a source for confusion down the road and
|
||||||
|
// may cause some expensive and unnecessary work to be done.
|
||||||
userState.mConnection.cleanupService();
|
userState.mConnection.cleanupService();
|
||||||
mUserStates.remove(userState.mUserId);
|
mUserStates.remove(userState.mUserId);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -86,6 +86,7 @@ public class AttentionManagerServiceTest {
|
|||||||
UserState mUserState = new UserState(0,
|
UserState mUserState = new UserState(0,
|
||||||
mContext,
|
mContext,
|
||||||
mLock,
|
mLock,
|
||||||
|
mMockHandler,
|
||||||
componentName);
|
componentName);
|
||||||
mUserState.mService = new MockIAttentionService();
|
mUserState.mService = new MockIAttentionService();
|
||||||
mSpyUserState = spy(mUserState);
|
mSpyUserState = spy(mUserState);
|
||||||
|
|||||||
Reference in New Issue
Block a user