diff options
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 dd2e0066a036..45a38be8aee4 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 5cf05f8ed9fb..ba6685aadd45 100644 --- a/packages/Keyguard/res/values/strings.xml +++ b/packages/Keyguard/res/values/strings.xml @@ -149,6 +149,14 @@ <!-- Shown on transport control of lockscreen. Pressing button pauses playback --> <string name="keyguard_accessibility_transport_stop_description">Stop button</string> + <!-- Accessibility description for when the device prompts the user to dismiss keyguard + in order to complete an action. This will be followed by a message about the current + security option (e.g. "Pattern unlock."). [CHAR LIMIT=NONE] --> + <string name="keyguard_accessibility_show_bouncer">Unlock to continue</string> + + <!-- Accessibility description for when the bouncer prompt is dismissed. [CHAR LIMIT=NONE] --> + <string name="keyguard_accessibility_hide_bouncer">Launch canceled</string> + <!-- Password keyboard strings. Used by LockScreen and Settings --><skip /> <!-- Label for "switch to symbols" key. Must be short to fit on key! --> <string name="password_keyboard_label_symbol_key">\?123</string> diff --git a/packages/Keyguard/src/com/android/keyguard/KeyguardHostView.java b/packages/Keyguard/src/com/android/keyguard/KeyguardHostView.java index aa4371120215..a9e9d3aaa6da 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 77006c5fef83..d7c5fe2f0c16 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 177e0f836151..a0e44d75247c 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 478096cc0acb..0606d838d915 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 d9f947191e42..d1862cd52f1c 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 765b274ab79b..aa7256bfaf33 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" /> <com.android.systemui.statusbar.policy.DeadZone @@ -297,6 +298,7 @@ android:src="@drawable/search_light" android:scaleType="center" android:visibility="gone" + android:contentDescription="@string/accessibility_search_light" /> <com.android.systemui.statusbar.policy.DeadZone diff --git a/packages/SystemUI/res/layout-sw600dp/navigation_bar.xml b/packages/SystemUI/res/layout-sw600dp/navigation_bar.xml index 9592b18cacda..b9ad7992bb2d 100644 --- a/packages/SystemUI/res/layout-sw600dp/navigation_bar.xml +++ b/packages/SystemUI/res/layout-sw600dp/navigation_bar.xml @@ -149,6 +149,7 @@ android:src="@drawable/search_light" android:scaleType="center" android:visibility="gone" + android:contentDescription="@string/accessibility_search_light" /> <com.android.systemui.statusbar.policy.DeadZone @@ -290,6 +291,7 @@ android:src="@drawable/search_light" android:scaleType="center" android:visibility="gone" + android:contentDescription="@string/accessibility_search_light" /> <com.android.systemui.statusbar.policy.DeadZone diff --git a/packages/SystemUI/res/layout/navigation_bar.xml b/packages/SystemUI/res/layout/navigation_bar.xml index 11cbbc787c33..aa365aedcfb1 100644 --- a/packages/SystemUI/res/layout/navigation_bar.xml +++ b/packages/SystemUI/res/layout/navigation_bar.xml @@ -157,6 +157,7 @@ android:src="@drawable/search_light" android:scaleType="center" android:visibility="gone" + android:contentDescription="@string/accessibility_search_light" /> <com.android.systemui.statusbar.policy.KeyButtonView @@ -167,6 +168,7 @@ android:src="@drawable/ic_sysbar_camera" android:scaleType="center" android:visibility="gone" + android:contentDescription="@string/accessibility_camera_button" /> </FrameLayout> @@ -312,6 +314,7 @@ android:src="@drawable/search_light" android:scaleType="center" android:visibility="gone" + android:contentDescription="@string/accessibility_search_light" /> <!-- No camera button in landscape mode --> diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml index eb425e66c92f..58865ab962bb 100644 --- a/packages/SystemUI/res/values/strings.xml +++ b/packages/SystemUI/res/values/strings.xml @@ -192,6 +192,10 @@ <string name="accessibility_menu">Menu</string> <!-- Content description of the recents button for accessibility (not shown on the screen). [CHAR LIMIT=NONE] --> <string name="accessibility_recent">Recent apps</string> + <!-- Content description of the search button for accessibility. [CHAR LIMIT=NONE] --> + <string name="accessibility_search_light">Search</string> + <!-- Content description of the camera button for accessibility (not shown on the screen). [CHAR LIMIT=NONE] --> + <string name="accessibility_camera_button">Camera</string> <!-- Content description of the switch input method button for accessibility (not shown on the screen). [CHAR LIMIT=NONE] --> <string name="accessibility_ime_switch_button">Switch input method button.</string> 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 a6e234777775..1221a557a314 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 24e27b1f2420..596fac601398 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 b27584da6dc2..5e299ee9a25b 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(); |