Print names of observers causing timeout
Pass and store name in registerUserSwitchObserver and later print names of
observers causing timeout.
Bug: 29039588
Change-Id: I09c4bcc986168a07f5e20ad0f38667b783332288
diff --git a/core/java/android/app/ActivityManagerNative.java b/core/java/android/app/ActivityManagerNative.java
index 3c7eef5..25c3d74 100644
--- a/core/java/android/app/ActivityManagerNative.java
+++ b/core/java/android/app/ActivityManagerNative.java
@@ -2370,7 +2370,8 @@
data.enforceInterface(IActivityManager.descriptor);
IUserSwitchObserver observer = IUserSwitchObserver.Stub.asInterface(
data.readStrongBinder());
- registerUserSwitchObserver(observer);
+ String name = data.readString();
+ registerUserSwitchObserver(observer, name);
reply.writeNoException();
return true;
}
@@ -6058,11 +6059,13 @@
return result;
}
- public void registerUserSwitchObserver(IUserSwitchObserver observer) throws RemoteException {
+ public void registerUserSwitchObserver(IUserSwitchObserver observer,
+ String name) throws RemoteException {
Parcel data = Parcel.obtain();
Parcel reply = Parcel.obtain();
data.writeInterfaceToken(IActivityManager.descriptor);
data.writeStrongBinder(observer != null ? observer.asBinder() : null);
+ data.writeString(name);
mRemote.transact(REGISTER_USER_SWITCH_OBSERVER_TRANSACTION, data, reply, 0);
reply.readException();
data.recycle();
diff --git a/core/java/android/app/IActivityManager.java b/core/java/android/app/IActivityManager.java
index ac21346..1197c84 100644
--- a/core/java/android/app/IActivityManager.java
+++ b/core/java/android/app/IActivityManager.java
@@ -512,7 +512,8 @@
public int getLaunchedFromUid(IBinder activityToken) throws RemoteException;
public String getLaunchedFromPackage(IBinder activityToken) throws RemoteException;
- public void registerUserSwitchObserver(IUserSwitchObserver observer) throws RemoteException;
+ public void registerUserSwitchObserver(IUserSwitchObserver observer,
+ String name) throws RemoteException;
public void unregisterUserSwitchObserver(IUserSwitchObserver observer) throws RemoteException;
public void requestBugReport(int bugreportType) throws RemoteException;
diff --git a/packages/Keyguard/src/com/android/keyguard/KeyguardUpdateMonitor.java b/packages/Keyguard/src/com/android/keyguard/KeyguardUpdateMonitor.java
index a8419bf..94d9550 100644
--- a/packages/Keyguard/src/com/android/keyguard/KeyguardUpdateMonitor.java
+++ b/packages/Keyguard/src/com/android/keyguard/KeyguardUpdateMonitor.java
@@ -1040,10 +1040,9 @@
public void onForegroundProfileSwitch(int newProfileId) {
// Ignore.
}
- });
+ }, TAG);
} catch (RemoteException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
+ e.rethrowAsRuntimeException();
}
IntentFilter strongAuthTimeoutFilter = new IntentFilter();
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java
index 81c0d81..a13138d 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java
@@ -144,7 +144,7 @@
// listen for user / profile change.
try {
- ActivityManagerNative.getDefault().registerUserSwitchObserver(mUserSwitchListener);
+ ActivityManagerNative.getDefault().registerUserSwitchObserver(mUserSwitchListener, TAG);
} catch (RemoteException e) {
// Ignore
}
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index e6a6388..faab7c9 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -21320,8 +21320,8 @@
}
@Override
- public void registerUserSwitchObserver(IUserSwitchObserver observer) {
- mUserController.registerUserSwitchObserver(observer);
+ public void registerUserSwitchObserver(IUserSwitchObserver observer, String name) {
+ mUserController.registerUserSwitchObserver(observer, name);
}
@Override
diff --git a/services/core/java/com/android/server/am/UserController.java b/services/core/java/com/android/server/am/UserController.java
index 597b499..152d34d 100644
--- a/services/core/java/com/android/server/am/UserController.java
+++ b/services/core/java/com/android/server/am/UserController.java
@@ -76,6 +76,7 @@
import android.os.UserManagerInternal;
import android.os.storage.IMountService;
import android.os.storage.StorageManager;
+import android.util.ArraySet;
import android.util.IntArray;
import android.util.Pair;
import android.util.Slog;
@@ -86,6 +87,7 @@
import com.android.internal.annotations.GuardedBy;
import com.android.internal.logging.MetricsLogger;
import com.android.internal.util.ArrayUtils;
+import com.android.internal.util.Preconditions;
import com.android.internal.widget.LockPatternUtils;
import com.android.server.LocalServices;
import com.android.server.pm.UserManagerService;
@@ -151,9 +153,9 @@
= new RemoteCallbackList<>();
/**
- * Currently active user switch.
+ * Currently active user switch callbacks.
*/
- Object mCurUserSwitchCallback;
+ private volatile ArraySet<String> mCurWaitingUserSwitchCallbacks;
private volatile UserManagerService mUserManager;
@@ -1040,7 +1042,8 @@
void timeoutUserSwitch(UserState uss, int oldUserId, int newUserId) {
synchronized (mService) {
- Slog.wtf(TAG, "User switch timeout: from " + oldUserId + " to " + newUserId);
+ Slog.wtf(TAG, "User switch timeout: from " + oldUserId + " to " + newUserId
+ + ". Observers that didn't send results: " + mCurWaitingUserSwitchCallbacks);
sendContinueUserSwitchLocked(uss, oldUserId, newUserId);
}
}
@@ -1049,28 +1052,34 @@
Slog.d(TAG, "Dispatch onUserSwitching oldUser #" + oldUserId + " newUser #" + newUserId);
final int observerCount = mUserSwitchObservers.beginBroadcast();
if (observerCount > 0) {
- final IRemoteCallback callback = new IRemoteCallback.Stub() {
- int mCount = 0;
- @Override
- public void sendResult(Bundle data) throws RemoteException {
- synchronized (mService) {
- if (mCurUserSwitchCallback == this) {
- mCount++;
- if (mCount == observerCount) {
- sendContinueUserSwitchLocked(uss, oldUserId, newUserId);
- }
- }
- }
- }
- };
+ final ArraySet<String> curWaitingUserSwitchCallbacks = new ArraySet<>();
synchronized (mService) {
uss.switching = true;
- mCurUserSwitchCallback = callback;
+ mCurWaitingUserSwitchCallbacks = curWaitingUserSwitchCallbacks;
}
for (int i = 0; i < observerCount; i++) {
try {
- mUserSwitchObservers.getBroadcastItem(i).onUserSwitching(
- newUserId, callback);
+ // Prepend with unique prefix to guarantee that keys are unique
+ final String name = "#" + i + " " + mUserSwitchObservers.getBroadcastCookie(i);
+ mCurWaitingUserSwitchCallbacks.add(name);
+ final IRemoteCallback callback = new IRemoteCallback.Stub() {
+ @Override
+ public void sendResult(Bundle data) throws RemoteException {
+ synchronized (mService) {
+ // Early return if this session is no longer valid
+ if (curWaitingUserSwitchCallbacks
+ != mCurWaitingUserSwitchCallbacks) {
+ return;
+ }
+ curWaitingUserSwitchCallbacks.remove(name);
+ // Continue switching if all callbacks have been notified
+ if (curWaitingUserSwitchCallbacks.isEmpty()) {
+ sendContinueUserSwitchLocked(uss, oldUserId, newUserId);
+ }
+ }
+ }
+ };
+ mUserSwitchObservers.getBroadcastItem(i).onUserSwitching(newUserId, callback);
} catch (RemoteException e) {
}
}
@@ -1083,7 +1092,7 @@
}
void sendContinueUserSwitchLocked(UserState uss, int oldUserId, int newUserId) {
- mCurUserSwitchCallback = null;
+ mCurWaitingUserSwitchCallbacks = null;
mHandler.removeMessages(USER_SWITCH_TIMEOUT_MSG);
mHandler.sendMessage(mHandler.obtainMessage(ActivityManagerService.CONTINUE_USER_SWITCH_MSG,
oldUserId, newUserId, uss));
@@ -1248,7 +1257,8 @@
? getCurrentUserIdLocked(): userId;
}
- void registerUserSwitchObserver(IUserSwitchObserver observer) {
+ void registerUserSwitchObserver(IUserSwitchObserver observer, String name) {
+ Preconditions.checkNotNull(name, "Observer name cannot be null");
if (mService.checkCallingPermission(INTERACT_ACROSS_USERS_FULL)
!= PackageManager.PERMISSION_GRANTED) {
final String msg = "Permission Denial: registerUserSwitchObserver() from pid="
@@ -1258,8 +1268,7 @@
Slog.w(TAG, msg);
throw new SecurityException(msg);
}
-
- mUserSwitchObservers.register(observer);
+ mUserSwitchObservers.register(observer, name);
}
void unregisterUserSwitchObserver(IUserSwitchObserver observer) {
diff --git a/services/core/java/com/android/server/fingerprint/FingerprintService.java b/services/core/java/com/android/server/fingerprint/FingerprintService.java
index cc556c7..14e4bc6 100644
--- a/services/core/java/com/android/server/fingerprint/FingerprintService.java
+++ b/services/core/java/com/android/server/fingerprint/FingerprintService.java
@@ -1013,7 +1013,7 @@
public void onForegroundProfileSwitch(int newProfileId) {
// Ignore.
}
- });
+ }, TAG);
} catch (RemoteException e) {
Slog.w(TAG, "Failed to listen for user switching event" ,e);
}
diff --git a/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java b/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java
index efd2382..7c2ba1e 100644
--- a/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java
+++ b/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java
@@ -906,10 +906,9 @@
public void onForegroundProfileSwitch(int newProfileId) {
// Ignore.
}
- });
+ }, TAG);
} catch (RemoteException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
+ e.rethrowAsRuntimeException();
}
}