Skip to content

Commit 5642a48

Browse files
author
Craig Mautner
committed
Fix unprotected variable access by serializing.
The variables mKeyguardDisabled and mAllowDisableKeyguard were being modified unprotected by mKeyguardTokenWatcher. Fix is to serialize accesses to these variables by only referencing them from the same Handler that mKeyguardTokenWatcher uses. Eliminates synchronization blocks and mKeyguardDisabled variable. Fixes bug 7045624. Change-Id: I6355aa393507408296316bee61e178dc81e2a172
1 parent 6715d1e commit 5642a48

File tree

2 files changed

+118
-81
lines changed

2 files changed

+118
-81
lines changed
Lines changed: 107 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,107 @@
1+
/*
2+
* Copyright (C) 2012 The Android Open Source Project
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package com.android.server.wm;
18+
19+
import android.app.admin.DevicePolicyManager;
20+
import android.content.Context;
21+
import android.os.Handler;
22+
import android.os.IBinder;
23+
import android.os.Message;
24+
import android.os.TokenWatcher;
25+
import android.util.Log;
26+
import android.util.Pair;
27+
import android.view.WindowManagerPolicy;
28+
29+
public class KeyguardDisableHandler extends Handler {
30+
private static final String TAG = "KeyguardDisableHandler";
31+
32+
private static final int ALLOW_DISABLE_YES = 1;
33+
private static final int ALLOW_DISABLE_NO = 0;
34+
private static final int ALLOW_DISABLE_UNKNOWN = -1; // check with DevicePolicyManager
35+
private int mAllowDisableKeyguard = ALLOW_DISABLE_UNKNOWN; // sync'd by mKeyguardTokenWatcher
36+
37+
// Message.what constants
38+
static final int KEYGUARD_DISABLE = 1;
39+
static final int KEYGUARD_REENABLE = 2;
40+
static final int KEYGUARD_POLICY_CHANGED = 3;
41+
42+
final Context mContext;
43+
final WindowManagerPolicy mPolicy;
44+
KeyguardTokenWatcher mKeyguardTokenWatcher;
45+
46+
public KeyguardDisableHandler(final Context context, final WindowManagerPolicy policy) {
47+
mContext = context;
48+
mPolicy = policy;
49+
}
50+
51+
@SuppressWarnings("unchecked")
52+
@Override
53+
public void handleMessage(Message msg) {
54+
if (mKeyguardTokenWatcher == null) {
55+
mKeyguardTokenWatcher = new KeyguardTokenWatcher(this);
56+
}
57+
58+
switch (msg.what) {
59+
case KEYGUARD_DISABLE:
60+
final Pair<IBinder, String> pair = (Pair<IBinder, String>)msg.obj;
61+
mKeyguardTokenWatcher.acquire(pair.first, pair.second);
62+
break;
63+
64+
case KEYGUARD_REENABLE:
65+
mKeyguardTokenWatcher.release((IBinder)msg.obj);
66+
break;
67+
68+
case KEYGUARD_POLICY_CHANGED:
69+
mPolicy.enableKeyguard(true);
70+
// lazily evaluate this next time we're asked to disable keyguard
71+
mAllowDisableKeyguard = ALLOW_DISABLE_UNKNOWN;
72+
break;
73+
}
74+
}
75+
76+
class KeyguardTokenWatcher extends TokenWatcher {
77+
78+
public KeyguardTokenWatcher(final Handler handler) {
79+
super(handler, TAG);
80+
}
81+
82+
@Override
83+
public void acquired() {
84+
// We fail safe and prevent disabling keyguard in the unlikely event this gets
85+
// called before DevicePolicyManagerService has started.
86+
if (mAllowDisableKeyguard == ALLOW_DISABLE_UNKNOWN) {
87+
DevicePolicyManager dpm = (DevicePolicyManager) mContext.getSystemService(
88+
Context.DEVICE_POLICY_SERVICE);
89+
if (dpm != null) {
90+
mAllowDisableKeyguard = dpm.getPasswordQuality(null)
91+
== DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED ?
92+
ALLOW_DISABLE_YES : ALLOW_DISABLE_NO;
93+
}
94+
}
95+
if (mAllowDisableKeyguard == ALLOW_DISABLE_YES) {
96+
mPolicy.enableKeyguard(false);
97+
} else {
98+
Log.v(TAG, "Not disabling keyguard since device policy is enforced");
99+
}
100+
}
101+
102+
@Override
103+
public void released() {
104+
mPolicy.enableKeyguard(true);
105+
}
106+
}
107+
}

services/java/com/android/server/wm/WindowManagerService.java

Lines changed: 11 additions & 81 deletions
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,6 @@
7575
import android.graphics.RectF;
7676
import android.graphics.Region;
7777
import android.hardware.display.DisplayManager;
78-
import android.os.BatteryStats;
7978
import android.os.Binder;
8079
import android.os.Bundle;
8180
import android.os.Debug;
@@ -93,7 +92,6 @@
9392
import android.os.StrictMode;
9493
import android.os.SystemClock;
9594
import android.os.SystemProperties;
96-
import android.os.TokenWatcher;
9795
import android.os.Trace;
9896
import android.os.WorkSource;
9997
import android.provider.Settings;
@@ -279,55 +277,19 @@ public class WindowManagerService extends IWindowManager.Stub
279277
private static final String SYSTEM_SECURE = "ro.secure";
280278
private static final String SYSTEM_DEBUGGABLE = "ro.debuggable";
281279

282-
/**
283-
* Condition waited on by {@link #reenableKeyguard} to know the call to
284-
* the window policy has finished.
285-
* This is set to true only if mKeyguardTokenWatcher.acquired() has
286-
* actually disabled the keyguard.
287-
*/
288-
private boolean mKeyguardDisabled = false;
280+
final private KeyguardDisableHandler mKeyguardDisableHandler;
289281

290282
private final boolean mHeadless;
291283

292-
private static final int ALLOW_DISABLE_YES = 1;
293-
private static final int ALLOW_DISABLE_NO = 0;
294-
private static final int ALLOW_DISABLE_UNKNOWN = -1; // check with DevicePolicyManager
295-
private int mAllowDisableKeyguard = ALLOW_DISABLE_UNKNOWN; // sync'd by mKeyguardTokenWatcher
296-
297284
private static final float THUMBNAIL_ANIMATION_DECELERATE_FACTOR = 1.5f;
298285

299-
final TokenWatcher mKeyguardTokenWatcher = new TokenWatcher(
300-
new Handler(), "WindowManagerService.mKeyguardTokenWatcher") {
301-
@Override
302-
public void acquired() {
303-
if (shouldAllowDisableKeyguard()) {
304-
mPolicy.enableKeyguard(false);
305-
mKeyguardDisabled = true;
306-
} else {
307-
Log.v(TAG, "Not disabling keyguard since device policy is enforced");
308-
}
309-
}
310-
@Override
311-
public void released() {
312-
mPolicy.enableKeyguard(true);
313-
synchronized (mKeyguardTokenWatcher) {
314-
mKeyguardDisabled = false;
315-
mKeyguardTokenWatcher.notifyAll();
316-
}
317-
}
318-
};
319-
320286
final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {
321287
@Override
322288
public void onReceive(Context context, Intent intent) {
323289
final String action = intent.getAction();
324290
if (DevicePolicyManager.ACTION_DEVICE_POLICY_MANAGER_STATE_CHANGED.equals(action)) {
325-
mPolicy.enableKeyguard(true);
326-
synchronized(mKeyguardTokenWatcher) {
327-
// lazily evaluate this next time we're asked to disable keyguard
328-
mAllowDisableKeyguard = ALLOW_DISABLE_UNKNOWN;
329-
mKeyguardDisabled = false;
330-
}
291+
mKeyguardDisableHandler.sendEmptyMessage(
292+
KeyguardDisableHandler.KEYGUARD_POLICY_CHANGED);
331293
} else if (Intent.ACTION_USER_SWITCHED.equals(action)) {
332294
final int newUserId = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, 0);
333295
Slog.v(TAG, "Switching user from " + mCurrentUserId + " to " + newUserId);
@@ -898,6 +860,8 @@ private WindowManagerService(Context context, PowerManagerService pm,
898860
mDisplayManager = DisplayManager.getInstance();
899861
mHeadless = displayManager.isHeadless();
900862

863+
mKeyguardDisableHandler = new KeyguardDisableHandler(mContext, mPolicy);
864+
901865
mPowerManager = pm;
902866
mPowerManager.setPolicy(mPolicy);
903867
PowerManager pmc = (PowerManager)context.getSystemService(Context.POWER_SERVICE);
@@ -5062,59 +5026,26 @@ public void moveAppTokensToBottom(List<IBinder> tokens) {
50625026
// Misc IWindowSession methods
50635027
// -------------------------------------------------------------
50645028

5065-
private boolean shouldAllowDisableKeyguard()
5066-
{
5067-
// We fail safe and prevent disabling keyguard in the unlikely event this gets
5068-
// called before DevicePolicyManagerService has started.
5069-
if (mAllowDisableKeyguard == ALLOW_DISABLE_UNKNOWN) {
5070-
DevicePolicyManager dpm = (DevicePolicyManager) mContext.getSystemService(
5071-
Context.DEVICE_POLICY_SERVICE);
5072-
if (dpm != null) {
5073-
mAllowDisableKeyguard = dpm.getPasswordQuality(null)
5074-
== DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED ?
5075-
ALLOW_DISABLE_YES : ALLOW_DISABLE_NO;
5076-
}
5077-
}
5078-
return mAllowDisableKeyguard == ALLOW_DISABLE_YES;
5079-
}
5080-
5029+
@Override
50815030
public void disableKeyguard(IBinder token, String tag) {
50825031
if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DISABLE_KEYGUARD)
50835032
!= PackageManager.PERMISSION_GRANTED) {
50845033
throw new SecurityException("Requires DISABLE_KEYGUARD permission");
50855034
}
50865035

5087-
synchronized (mKeyguardTokenWatcher) {
5088-
mKeyguardTokenWatcher.acquire(token, tag);
5089-
}
5036+
mKeyguardDisableHandler.sendMessage(mKeyguardDisableHandler.obtainMessage(
5037+
KeyguardDisableHandler.KEYGUARD_DISABLE, new Pair<IBinder, String>(token, tag)));
50905038
}
50915039

5040+
@Override
50925041
public void reenableKeyguard(IBinder token) {
50935042
if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DISABLE_KEYGUARD)
50945043
!= PackageManager.PERMISSION_GRANTED) {
50955044
throw new SecurityException("Requires DISABLE_KEYGUARD permission");
50965045
}
50975046

5098-
synchronized (mKeyguardTokenWatcher) {
5099-
mKeyguardTokenWatcher.release(token);
5100-
5101-
if (!mKeyguardTokenWatcher.isAcquired()) {
5102-
// If we are the last one to reenable the keyguard wait until
5103-
// we have actually finished reenabling until returning.
5104-
// It is possible that reenableKeyguard() can be called before
5105-
// the previous disableKeyguard() is handled, in which case
5106-
// neither mKeyguardTokenWatcher.acquired() or released() would
5107-
// be called. In that case mKeyguardDisabled will be false here
5108-
// and we have nothing to wait for.
5109-
while (mKeyguardDisabled) {
5110-
try {
5111-
mKeyguardTokenWatcher.wait();
5112-
} catch (InterruptedException e) {
5113-
Thread.currentThread().interrupt();
5114-
}
5115-
}
5116-
}
5117-
}
5047+
mKeyguardDisableHandler.sendMessage(mKeyguardDisableHandler.obtainMessage(
5048+
KeyguardDisableHandler.KEYGUARD_REENABLE, token));
51185049
}
51195050

51205051
/**
@@ -10416,7 +10347,6 @@ public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
1041610347
// Called by the heartbeat to ensure locks are not held indefnitely (for deadlock detection).
1041710348
public void monitor() {
1041810349
synchronized (mWindowMap) { }
10419-
synchronized (mKeyguardTokenWatcher) { }
1042010350
}
1042110351

1042210352
public interface OnHardKeyboardStatusChangeListener {

0 commit comments

Comments
 (0)