From 138f25d75665bd07d34294364c5b6f530b33503f Mon Sep 17 00:00:00 2001 From: Jim Miller Date: Wed, 25 Sep 2013 13:46:58 -0700 Subject: [PATCH] Accessibility improvements in keyguard - add accessibility descriptions to camera and search light - add new onClick handler to simplify launching search and camera - plumb camera launch through KeyguardService interface Fixes bug 10914360 Change-Id: Ic85eda9afadba7381be78b477180f7204030cd17 --- .../internal/policy/IKeyguardService.aidl | 1 + packages/Keyguard/res/values/strings.xml | 8 +++ .../android/keyguard/KeyguardHostView.java | 15 ++++-- .../com/android/keyguard/KeyguardService.java | 4 ++ .../android/keyguard/KeyguardViewManager.java | 6 +++ .../keyguard/KeyguardViewMediator.java | 13 +++++ .../keyguard/KeyguardViewStateManager.java | 5 ++ .../res/layout-ldrtl/navigation_bar.xml | 2 + .../res/layout-sw600dp/navigation_bar.xml | 2 + .../SystemUI/res/layout/navigation_bar.xml | 3 ++ packages/SystemUI/res/values/strings.xml | 4 ++ .../phone/KeyguardTouchDelegate.java | 26 ++++++++++ .../statusbar/phone/NavigationBarView.java | 52 +++++++++++++++---- .../impl/keyguard/KeyguardServiceWrapper.java | 4 ++ 14 files changed, 132 insertions(+), 13 deletions(-) diff --git a/core/java/com/android/internal/policy/IKeyguardService.aidl b/core/java/com/android/internal/policy/IKeyguardService.aidl index dd2e0066a0368..45a38be8aee4f 100644 --- a/core/java/com/android/internal/policy/IKeyguardService.aidl +++ b/core/java/com/android/internal/policy/IKeyguardService.aidl @@ -42,4 +42,5 @@ interface IKeyguardService { oneway void setCurrentUser(int userId); oneway void showAssistant(); oneway void dispatch(in MotionEvent event); + oneway void launchCamera(); } diff --git a/packages/Keyguard/res/values/strings.xml b/packages/Keyguard/res/values/strings.xml index 5cf05f8ed9fb7..ba6685aadd452 100644 --- a/packages/Keyguard/res/values/strings.xml +++ b/packages/Keyguard/res/values/strings.xml @@ -149,6 +149,14 @@ Stop button + + Unlock to continue + + + Launch canceled + \?123 diff --git a/packages/Keyguard/src/com/android/keyguard/KeyguardHostView.java b/packages/Keyguard/src/com/android/keyguard/KeyguardHostView.java index aa43711202150..a9e9d3aaa6da3 100644 --- a/packages/Keyguard/src/com/android/keyguard/KeyguardHostView.java +++ b/packages/Keyguard/src/com/android/keyguard/KeyguardHostView.java @@ -24,7 +24,6 @@ import android.app.Activity; import android.app.ActivityManager; import android.app.ActivityOptions; import android.app.AlertDialog; -import android.app.PendingIntent; import android.app.SearchManager; import android.app.admin.DevicePolicyManager; import android.appwidget.AppWidgetHost; @@ -41,7 +40,6 @@ import android.content.res.Resources; import android.graphics.Canvas; import android.graphics.Rect; import android.media.RemoteControlClient; -import android.os.Bundle; import android.os.Looper; import android.os.Parcel; import android.os.Parcelable; @@ -49,11 +47,9 @@ import android.os.SystemClock; import android.os.UserHandle; import android.os.UserManager; import android.provider.Settings; -import android.telephony.TelephonyManager; import android.util.AttributeSet; import android.util.Log; import android.util.Slog; -import android.view.KeyEvent; import android.view.LayoutInflater; import android.view.MotionEvent; import android.view.View; @@ -206,6 +202,13 @@ public class KeyguardHostView extends KeyguardViewBase { } } + public void announceCurrentSecurityMethod() { + View v = (View) getSecurityView(mCurrentSecuritySelection); + if (v != null) { + v.announceForAccessibility(v.getContentDescription()); + } + } + private void getInitialTransportState() { DisplayClientState dcs = KeyguardUpdateMonitor.getInstance(mContext) .getCachedDisplayClientState(); @@ -1663,4 +1666,8 @@ public class KeyguardHostView extends KeyguardViewBase { mAppWidgetContainer.handleExternalCameraEvent(event); } + public void launchCamera() { + mActivityLauncher.launchCamera(getHandler(), null); + } + } diff --git a/packages/Keyguard/src/com/android/keyguard/KeyguardService.java b/packages/Keyguard/src/com/android/keyguard/KeyguardService.java index 77006c5fef83e..d7c5fe2f0c16c 100644 --- a/packages/Keyguard/src/com/android/keyguard/KeyguardService.java +++ b/packages/Keyguard/src/com/android/keyguard/KeyguardService.java @@ -137,6 +137,10 @@ public class KeyguardService extends Service { checkPermission(); mKeyguardViewMediator.dispatch(event); } + public void launchCamera() { + checkPermission(); + mKeyguardViewMediator.launchCamera(); + } }; } diff --git a/packages/Keyguard/src/com/android/keyguard/KeyguardViewManager.java b/packages/Keyguard/src/com/android/keyguard/KeyguardViewManager.java index 177e0f8361510..a0e44d75247c9 100644 --- a/packages/Keyguard/src/com/android/keyguard/KeyguardViewManager.java +++ b/packages/Keyguard/src/com/android/keyguard/KeyguardViewManager.java @@ -506,4 +506,10 @@ public class KeyguardViewManager { mKeyguardView.dispatch(event); } } + + public void launchCamera() { + if (mKeyguardView != null) { + mKeyguardView.launchCamera(); + } + } } diff --git a/packages/Keyguard/src/com/android/keyguard/KeyguardViewMediator.java b/packages/Keyguard/src/com/android/keyguard/KeyguardViewMediator.java index 478096cc0acb5..0606d838d915e 100644 --- a/packages/Keyguard/src/com/android/keyguard/KeyguardViewMediator.java +++ b/packages/Keyguard/src/com/android/keyguard/KeyguardViewMediator.java @@ -122,6 +122,7 @@ public class KeyguardViewMediator { private static final int KEYGUARD_TIMEOUT = 13; private static final int SHOW_ASSISTANT = 14; private static final int DISPATCH_EVENT = 15; + private static final int LAUNCH_CAMERA = 16; /** * The default amount of time we stay awake (used for all key input) @@ -1071,6 +1072,9 @@ public class KeyguardViewMediator { case DISPATCH_EVENT: handleDispatchEvent((MotionEvent) msg.obj); break; + case LAUNCH_CAMERA: + handleLaunchCamera(); + break; } } }; @@ -1107,6 +1111,10 @@ public class KeyguardViewMediator { sendUserPresentBroadcast(); } + protected void handleLaunchCamera() { + mKeyguardViewManager.launchCamera(); + } + protected void handleDispatchEvent(MotionEvent event) { mKeyguardViewManager.dispatch(event); } @@ -1341,4 +1349,9 @@ public class KeyguardViewMediator { Message msg = mHandler.obtainMessage(DISPATCH_EVENT, event); mHandler.sendMessage(msg); } + + public void launchCamera() { + Message msg = mHandler.obtainMessage(LAUNCH_CAMERA); + mHandler.sendMessage(msg); + } } diff --git a/packages/Keyguard/src/com/android/keyguard/KeyguardViewStateManager.java b/packages/Keyguard/src/com/android/keyguard/KeyguardViewStateManager.java index d9f947191e42c..d1862cd52f1c3 100644 --- a/packages/Keyguard/src/com/android/keyguard/KeyguardViewStateManager.java +++ b/packages/Keyguard/src/com/android/keyguard/KeyguardViewStateManager.java @@ -87,6 +87,11 @@ public class KeyguardViewStateManager implements } public void showBouncer(boolean show) { + CharSequence what = mKeyguardHostView.getContext().getResources().getText( + show ? R.string.keyguard_accessibility_show_bouncer + : R.string.keyguard_accessibility_hide_bouncer); + mKeyguardHostView.announceForAccessibility(what); + mKeyguardHostView.announceCurrentSecurityMethod(); mChallengeLayout.showBouncer(); } diff --git a/packages/SystemUI/res/layout-ldrtl/navigation_bar.xml b/packages/SystemUI/res/layout-ldrtl/navigation_bar.xml index 765b274ab79b0..aa7256bfaf333 100644 --- a/packages/SystemUI/res/layout-ldrtl/navigation_bar.xml +++ b/packages/SystemUI/res/layout-ldrtl/navigation_bar.xml @@ -153,6 +153,7 @@ android:src="@drawable/search_light" android:scaleType="center" android:visibility="gone" + android:contentDescription="@string/accessibility_search_light" /> @@ -312,6 +314,7 @@ android:src="@drawable/search_light" android:scaleType="center" android:visibility="gone" + android:contentDescription="@string/accessibility_search_light" /> diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml index eb425e66c92f4..58865ab962bbf 100644 --- a/packages/SystemUI/res/values/strings.xml +++ b/packages/SystemUI/res/values/strings.xml @@ -192,6 +192,10 @@ Menu Recent apps + + Search + + Camera Switch input method button. diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardTouchDelegate.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardTouchDelegate.java index a6e234777775e..1221a557a3145 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardTouchDelegate.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardTouchDelegate.java @@ -103,4 +103,30 @@ public class KeyguardTouchDelegate { return false; } + public void showAssistant() { + if (mService != null) { + try { + mService.showAssistant(); + } catch (RemoteException e) { + // What to do? + Log.e(TAG, "RemoteException launching assistant!", e); + } + } else { + Log.w(TAG, "dispatch(event): NO SERVICE!"); + } + } + + public void launchCamera() { + if (mService != null) { + try { + mService.launchCamera(); + } catch (RemoteException e) { + // What to do? + Log.e(TAG, "RemoteException launching camera!", e); + } + } else { + Log.w(TAG, "dispatch(event): NO SERVICE!"); + } + } + } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java index 24e27b1f24209..596fac6013984 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java @@ -37,8 +37,10 @@ import android.view.Display; import android.view.MotionEvent; import android.view.Surface; import android.view.View; +import android.view.View.OnClickListener; import android.view.ViewGroup; import android.view.WindowManager; +import android.view.accessibility.AccessibilityManager; import android.widget.ImageView; import android.widget.LinearLayout; @@ -86,7 +88,7 @@ public class NavigationBarView extends LinearLayout { // used to disable the camera icon in navbar when disabled by DPM private boolean mCameraDisabledByDpm; - KeyguardTouchDelegate mTouchDelegate; + KeyguardTouchDelegate mKeyguardTouchDelegate; private final OnTouchListener mCameraTouchListener = new OnTouchListener() { @Override @@ -110,7 +112,7 @@ public class NavigationBarView extends LinearLayout { } break; } - return mTouchDelegate.dispatch(event); + return mKeyguardTouchDelegate.dispatch(event); } }; @@ -153,7 +155,7 @@ public class NavigationBarView extends LinearLayout { mBarTransitions = new NavigationBarTransitions(this); - mTouchDelegate = new KeyguardTouchDelegate(mContext); + mKeyguardTouchDelegate = new KeyguardTouchDelegate(mContext); mCameraDisabledByDpm = isCameraDisabledByDpm(); watchForDevicePolicyChanges(); @@ -339,7 +341,7 @@ public class NavigationBarView extends LinearLayout { final int disabledFlags = dpm.getKeyguardDisabledFeatures(null, userId); final boolean disabledBecauseKeyguardSecure = (disabledFlags & DevicePolicyManager.KEYGUARD_DISABLE_SECURE_CAMERA) != 0 - && mTouchDelegate.isSecure(); + && mKeyguardTouchDelegate.isSecure(); return dpm.getCameraDisabled(null) || disabledBecauseKeyguardSecure; } catch (RemoteException e) { Log.e(TAG, "Can't get userId", e); @@ -389,12 +391,44 @@ public class NavigationBarView extends LinearLayout { mCurrentView = mRotatedViews[Surface.ROTATION_0]; - // Add a touch handler for camera icon for all view orientations. - for (int i = 0; i < mRotatedViews.length; i++) { - View cameraButton = mRotatedViews[i].findViewById(R.id.camera_button); - if (cameraButton != null) { - cameraButton.setOnTouchListener(mCameraTouchListener); + + final AccessibilityManager accessibilityManager = + (AccessibilityManager) mContext.getSystemService(Context.ACCESSIBILITY_SERVICE); + if (accessibilityManager.isEnabled()) { + // In accessibility mode, we add a simple click handler since swipe is tough to + // trigger near screen edges. + View camera = getCameraButton(); + View searchLight = getSearchLight(); + if (camera != null || searchLight != null) { + OnClickListener listener = new OnClickListener() { + @Override + public void onClick(View v) { + launchForAccessibilityClick(v); + } + }; + if (camera != null) { + camera.setOnClickListener(listener); + } + if (searchLight != null) { + searchLight.setOnClickListener(listener); + } } + } else { + // Add a touch handler for camera icon for all view orientations. + for (int i = 0; i < mRotatedViews.length; i++) { + View cameraButton = mRotatedViews[i].findViewById(R.id.camera_button); + if (cameraButton != null) { + cameraButton.setOnTouchListener(mCameraTouchListener); + } + } + } + } + + protected void launchForAccessibilityClick(View v) { + if (v == getCameraButton()) { + mKeyguardTouchDelegate.launchCamera(); + } else if (v == getSearchLight()) { + mKeyguardTouchDelegate.showAssistant(); } } diff --git a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardServiceWrapper.java b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardServiceWrapper.java index b27584da6dc26..5e299ee9a25bb 100644 --- a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardServiceWrapper.java +++ b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardServiceWrapper.java @@ -192,6 +192,10 @@ public class KeyguardServiceWrapper implements IKeyguardService { // Not used by PhoneWindowManager. See code in {@link NavigationBarView} } + public void launchCamera() { + // Not used by PhoneWindowManager. See code in {@link NavigationBarView} + } + @Override public IBinder asBinder() { return mService.asBinder();