Merge "Keyguard: Fix threading issues in KeyguardUpdateMonitor" into pi-dev

This commit is contained in:
android-build-team Robot
2018-04-30 11:29:56 +00:00
committed by Android (Google) Code Review
3 changed files with 69 additions and 25 deletions

View File

@@ -29,8 +29,11 @@ import static android.os.BatteryManager.EXTRA_MAX_CHARGING_VOLTAGE;
import static android.os.BatteryManager.EXTRA_PLUGGED;
import static android.os.BatteryManager.EXTRA_STATUS;
import android.annotation.AnyThread;
import android.annotation.MainThread;
import android.app.ActivityManager;
import android.app.AlarmManager;
import android.app.Instrumentation;
import android.app.PendingIntent;
import android.app.UserSwitchObserver;
import android.app.admin.DevicePolicyManager;
@@ -44,7 +47,6 @@ import android.content.pm.IPackageManager;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.database.ContentObserver;
import android.graphics.Bitmap;
import android.hardware.fingerprint.FingerprintManager;
import android.hardware.fingerprint.FingerprintManager.AuthenticationCallback;
import android.hardware.fingerprint.FingerprintManager.AuthenticationResult;
@@ -77,6 +79,7 @@ import com.android.internal.telephony.IccCardConstants;
import com.android.internal.telephony.IccCardConstants.State;
import com.android.internal.telephony.PhoneConstants;
import com.android.internal.telephony.TelephonyIntents;
import com.android.internal.util.Preconditions;
import com.android.internal.widget.LockPatternUtils;
import com.android.systemui.recents.misc.SysUiTaskStackChangeListener;
import com.android.systemui.shared.system.ActivityManagerWrapper;
@@ -355,6 +358,7 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener {
private static int sCurrentUser;
private Runnable mUpdateFingerprintListeningState = this::updateFingerprintListeningState;
private static boolean sDisableHandlerCheckForTesting;
public synchronized static void setCurrentUser(int currentUser) {
sCurrentUser = currentUser;
@@ -366,6 +370,7 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener {
@Override
public void onTrustChanged(boolean enabled, int userId, int flags) {
checkIsHandlerThread();
mUserHasTrust.put(userId, enabled);
for (int i = 0; i < mCallbacks.size(); i++) {
KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
@@ -383,7 +388,7 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener {
dispatchErrorMessage(message);
}
protected void handleSimSubscriptionInfoChanged() {
private void handleSimSubscriptionInfoChanged() {
if (DEBUG_SIM_STATES) {
Log.v(TAG, "onSubscriptionInfoChanged()");
List<SubscriptionInfo> sil = mSubscriptionManager.getActiveSubscriptionInfoList();
@@ -451,6 +456,7 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener {
@Override
public void onTrustManagedChanged(boolean managed, int userId) {
checkIsHandlerThread();
mUserTrustIsManaged.put(userId, managed);
for (int i = 0; i < mCallbacks.size(); i++) {
@@ -638,6 +644,7 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener {
}
private void notifyFingerprintRunningStateChanged() {
checkIsHandlerThread();
for (int i = 0; i < mCallbacks.size(); i++) {
KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
if (cb != null) {
@@ -646,6 +653,7 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener {
}
}
private void handleFaceUnlockStateChanged(boolean running, int userId) {
checkIsHandlerThread();
mUserFaceUnlockRunning.put(userId, running);
for (int i = 0; i < mCallbacks.size(); i++) {
KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
@@ -705,6 +713,7 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener {
}
private void notifyStrongAuthStateChanged(int userId) {
checkIsHandlerThread();
for (int i = 0; i < mCallbacks.size(); i++) {
KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
if (cb != null) {
@@ -1125,20 +1134,6 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener {
updateFingerprintListeningState();
}
/**
* IMPORTANT: Must be called from UI thread.
*/
public void dispatchSetBackground(Bitmap bmp) {
if (DEBUG) Log.d(TAG, "dispatchSetBackground");
final int count = mCallbacks.size();
for (int i = 0; i < count; i++) {
KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
if (cb != null) {
cb.onSetBackground(bmp);
}
}
}
private void handleUserInfoChanged(int userId) {
for (int i = 0; i < mCallbacks.size(); i++) {
KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
@@ -1350,6 +1345,7 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener {
* @param hasLockscreenWallpaper Whether Keyguard has a lockscreen wallpaper.
*/
public void setHasLockscreenWallpaper(boolean hasLockscreenWallpaper) {
checkIsHandlerThread();
if (hasLockscreenWallpaper != mHasLockscreenWallpaper) {
mHasLockscreenWallpaper = hasLockscreenWallpaper;
for (int i = mCallbacks.size() - 1; i >= 0; i--) {
@@ -1371,7 +1367,7 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener {
/**
* Handle {@link #MSG_DPM_STATE_CHANGED}
*/
protected void handleDevicePolicyManagerStateChanged() {
private void handleDevicePolicyManagerStateChanged() {
updateFingerprintListeningState();
for (int i = mCallbacks.size() - 1; i >= 0; i--) {
KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
@@ -1384,7 +1380,7 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener {
/**
* Handle {@link #MSG_USER_SWITCHING}
*/
protected void handleUserSwitching(int userId, IRemoteCallback reply) {
private void handleUserSwitching(int userId, IRemoteCallback reply) {
for (int i = 0; i < mCallbacks.size(); i++) {
KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
if (cb != null) {
@@ -1400,7 +1396,7 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener {
/**
* Handle {@link #MSG_USER_SWITCH_COMPLETE}
*/
protected void handleUserSwitchComplete(int userId) {
private void handleUserSwitchComplete(int userId) {
for (int i = 0; i < mCallbacks.size(); i++) {
KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
if (cb != null) {
@@ -1422,7 +1418,7 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener {
/**
* Handle {@link #MSG_BOOT_COMPLETED}
*/
protected void handleBootCompleted() {
private void handleBootCompleted() {
if (mBootCompleted) return;
mBootCompleted = true;
for (int i = 0; i < mCallbacks.size(); i++) {
@@ -1444,7 +1440,7 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener {
/**
* Handle {@link #MSG_DEVICE_PROVISIONED}
*/
protected void handleDeviceProvisioned() {
private void handleDeviceProvisioned() {
for (int i = 0; i < mCallbacks.size(); i++) {
KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
if (cb != null) {
@@ -1461,7 +1457,7 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener {
/**
* Handle {@link #MSG_PHONE_STATE_CHANGED}
*/
protected void handlePhoneStateChanged(String newState) {
private void handlePhoneStateChanged(String newState) {
if (DEBUG) Log.d(TAG, "handlePhoneStateChanged(" + newState + ")");
if (TelephonyManager.EXTRA_STATE_IDLE.equals(newState)) {
mPhoneState = TelephonyManager.CALL_STATE_IDLE;
@@ -1481,7 +1477,7 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener {
/**
* Handle {@link #MSG_RINGER_MODE_CHANGED}
*/
protected void handleRingerModeChange(int mode) {
private void handleRingerModeChange(int mode) {
if (DEBUG) Log.d(TAG, "handleRingerModeChange(" + mode + ")");
mRingMode = mode;
for (int i = 0; i < mCallbacks.size(); i++) {
@@ -1526,8 +1522,8 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener {
* Handle {@link #MSG_SIM_STATE_CHANGE}
*/
@VisibleForTesting
protected void handleSimStateChange(int subId, int slotId, State state) {
void handleSimStateChange(int subId, int slotId, State state) {
checkIsHandlerThread();
if (DEBUG_SIM_STATES) {
Log.d(TAG, "handleSimStateChange(subId=" + subId + ", slotId="
+ slotId + ", state=" + state +")");
@@ -1590,6 +1586,7 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener {
* <p>Needs to be called from the main thread.
*/
public void onKeyguardVisibilityChanged(boolean showing) {
checkIsHandlerThread();
if (DEBUG) Log.d(TAG, "onKeyguardVisibilityChanged(" + showing + ")");
mKeyguardIsVisible = showing;
for (int i = 0; i < mCallbacks.size(); i++) {
@@ -1680,6 +1677,7 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener {
* @param callback The callback to remove
*/
public void removeCallback(KeyguardUpdateMonitorCallback callback) {
checkIsHandlerThread();
if (DEBUG) Log.v(TAG, "*** unregister callback for " + callback);
for (int i = mCallbacks.size() - 1; i >= 0; i--) {
if (mCallbacks.get(i).get() == callback) {
@@ -1694,6 +1692,7 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener {
* @param callback The callback to register
*/
public void registerCallback(KeyguardUpdateMonitorCallback callback) {
checkIsHandlerThread();
if (DEBUG) Log.v(TAG, "*** register callback for " + callback);
// Prevent adding duplicate callbacks
for (int i = 0; i < mCallbacks.size(); i++) {
@@ -1712,6 +1711,7 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener {
return mSwitchingUser;
}
@AnyThread
public void setSwitchingUser(boolean switching) {
mSwitchingUser = switching;
// Since this comes in on a binder thread, we need to post if first
@@ -1755,6 +1755,7 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener {
* NOTE: Because handleSimStateChange() invokes callbacks immediately without going
* through mHandler, this *must* be called from the UI thread.
*/
@MainThread
public void reportSimUnlocked(int subId) {
if (DEBUG_SIM_STATES) Log.v(TAG, "reportSimUnlocked(subId=" + subId + ")");
int slotId = SubscriptionManager.getSlotIndex(subId);
@@ -1773,6 +1774,7 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener {
if (!bypassHandler) {
mHandler.obtainMessage(MSG_REPORT_EMERGENCY_CALL_ACTION).sendToTarget();
} else {
checkIsHandlerThread();
handleReportEmergencyCallAction();
}
}
@@ -1975,6 +1977,7 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener {
}
private void updateLogoutEnabled() {
checkIsHandlerThread();
boolean logoutEnabled = mDevicePolicyManager.isLogoutEnabled();
if (mLogoutEnabled != logoutEnabled) {
mLogoutEnabled = logoutEnabled;
@@ -1987,6 +1990,36 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener {
}
}
private void checkIsHandlerThread() {
if (sDisableHandlerCheckForTesting) {
return;
}
if (!mHandler.getLooper().isCurrentThread()) {
Log.wtf(TAG, "must call on mHandler's thread "
+ mHandler.getLooper().getThread() + ", not " + Thread.currentThread());
}
}
/**
* Turn off the handler check for testing.
*
* This is necessary because currently tests are not too careful about which thread they call
* into this class on.
*
* Note that this must be called before scheduling any work involving KeyguardUpdateMonitor
* instances.
*
* TODO: fix the tests and remove this.
*/
@VisibleForTesting
public static void disableHandlerCheckForTesting(Instrumentation instrumentation) {
Preconditions.checkNotNull(instrumentation, "Must only call this method in tests!");
// Don't need synchronization here *if* the callers follow the contract and call this only
// before scheduling work for KeyguardUpdateMonitor on other threads, because the scheduling
// of that work forces a happens-before relationship.
sDisableHandlerCheckForTesting = true;
}
public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
pw.println("KeyguardUpdateMonitor state:");
pw.println(" SIM States:");

View File

@@ -165,6 +165,7 @@ public class KeyguardViewMediator extends SystemUI {
private static final int NOTIFY_SCREEN_TURNED_ON = 15;
private static final int NOTIFY_SCREEN_TURNED_OFF = 16;
private static final int NOTIFY_STARTED_GOING_TO_SLEEP = 17;
private static final int SYSTEM_READY = 18;
/**
* The default amount of time we stay awake (used for all key input)
@@ -775,6 +776,10 @@ public class KeyguardViewMediator extends SystemUI {
* Let us know that the system is ready after startup.
*/
public void onSystemReady() {
mHandler.obtainMessage(SYSTEM_READY).sendToTarget();
}
private void handleSystemReady() {
synchronized (this) {
if (DEBUG) Log.d(TAG, "onSystemReady");
mSystemReady = true;
@@ -1603,6 +1608,9 @@ public class KeyguardViewMediator extends SystemUI {
Log.w(TAG, "Timeout while waiting for activity drawn!");
Trace.endSection();
break;
case SYSTEM_READY:
handleSystemReady();
break;
}
}
};

View File

@@ -28,6 +28,8 @@ import android.testing.DexmakerShareClassLoaderRule;
import android.testing.LeakCheck;
import android.util.Log;
import com.android.keyguard.KeyguardUpdateMonitor;
import org.junit.After;
import org.junit.Before;
import org.junit.Rule;
@@ -70,6 +72,7 @@ public abstract class SysuiTestCase {
"SysUI Tests should use SysuiTestCase#getContext or SysuiTestCase#mContext");
});
InstrumentationRegistry.registerInstance(inst, InstrumentationRegistry.getArguments());
KeyguardUpdateMonitor.disableHandlerCheckForTesting(inst);
}
@After