Accessibility enhancements within quick settings and notification shade.

Change-Id: I377c389abe3ce2285a620e60f4c8de4727f4f5c9
Bug: 7229886
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
index e88f9cd..3e929d6 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
@@ -301,8 +301,12 @@
             final int _id = n.id;
             vetoButton.setOnClickListener(new View.OnClickListener() {
                     public void onClick(View v) {
+                        // Accessibility feedback
+                        v.announceForAccessibility(
+                                mContext.getString(R.string.accessibility_notification_dismissed));
                         try {
                             mBarService.onNotificationClear(_pkg, _tag, _id);
+
                         } catch (RemoteException ex) {
                             // system process is dead if we're here.
                         }
@@ -312,6 +316,7 @@
         } else {
             vetoButton.setVisibility(View.GONE);
         }
+        vetoButton.setImportantForAccessibility(View.IMPORTANT_FOR_ACCESSIBILITY_NO);
         return vetoButton;
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
index 32b7c68..c832fb8 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
@@ -44,6 +44,8 @@
         mHandleBar = resources.getDrawable(R.drawable.status_bar_close);
         mHandleBarHeight = resources.getDimension(R.dimen.close_handle_height);
         mHandleView = findViewById(R.id.handle);
+
+        setContentDescription(resources.getString(R.string.accessibility_desc_notification_shade));
     }
 
     @Override
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarView.java
index 516b1ab..da31861 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarView.java
@@ -39,6 +39,7 @@
 
     boolean mFullWidthNotifications;
     PanelView mFadingPanel = null;
+    PanelView mLastFullyOpenedPanel = null;
     PanelView mNotificationPanel, mSettingsPanel;
     private boolean mShouldFade;
 
@@ -145,12 +146,17 @@
         super.onAllPanelsCollapsed();
         mBar.makeExpandedInvisible();
         mFadingPanel = null;
+        mLastFullyOpenedPanel = null;
     }
 
     @Override
     public void onPanelFullyOpened(PanelView openPanel) {
         super.onPanelFullyOpened(openPanel);
+        if (openPanel != mLastFullyOpenedPanel) {
+            openPanel.sendAccessibilityEvent(AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED);
+        }
         mFadingPanel = openPanel;
+        mLastFullyOpenedPanel = openPanel;
         mShouldFade = true; // now you own the fade, mister
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickSettings.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickSettings.java
index 2e298d1..e8772df 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickSettings.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickSettings.java
@@ -19,9 +19,12 @@
 import com.android.internal.view.RotationPolicy;
 import com.android.internal.widget.LockPatternUtils;
 import com.android.systemui.R;
+
+import com.android.systemui.statusbar.phone.QuickSettingsModel.BluetoothState;
 import com.android.systemui.statusbar.phone.QuickSettingsModel.RSSIState;
 import com.android.systemui.statusbar.phone.QuickSettingsModel.State;
 import com.android.systemui.statusbar.phone.QuickSettingsModel.UserState;
+import com.android.systemui.statusbar.phone.QuickSettingsModel.WifiState;
 import com.android.systemui.statusbar.policy.BatteryController;
 import com.android.systemui.statusbar.policy.BluetoothController;
 import com.android.systemui.statusbar.policy.BrightnessController;
@@ -90,7 +93,7 @@
     private DisplayManager mDisplayManager;
     private WifiDisplayStatus mWifiDisplayStatus;
     private PhoneStatusBar mStatusBarService;
-    private QuickSettingsModel.BluetoothState mBluetoothState;
+    private BluetoothState mBluetoothState;
 
     private BrightnessController mBrightnessController;
     private BluetoothController mBluetoothController;
@@ -305,6 +308,8 @@
                 if (us.avatar != null) {
                     iv.setImageDrawable(us.avatar);
                 }
+                view.setContentDescription(mContext.getString(
+                        R.string.accessibility_quick_settings_user, state.label));
             }
         });
         parent.addView(userTile);
@@ -363,9 +368,14 @@
         mModel.addWifiTile(wifiTile, new QuickSettingsModel.RefreshCallback() {
             @Override
             public void refreshView(QuickSettingsTileView view, State state) {
+                WifiState wifiState = (WifiState) state;
                 TextView tv = (TextView) view.findViewById(R.id.wifi_textview);
-                tv.setCompoundDrawablesWithIntrinsicBounds(0, state.iconId, 0, 0);
-                tv.setText(state.label);
+                tv.setCompoundDrawablesWithIntrinsicBounds(0, wifiState.iconId, 0, 0);
+                tv.setText(wifiState.label);
+                view.setContentDescription(mContext.getString(
+                        R.string.accessibility_quick_settings_wifi,
+                        wifiState.signalContentDescription,
+                        (wifiState.connected) ? wifiState.label : ""));
             }
         });
         parent.addView(wifiTile);
@@ -393,12 +403,17 @@
                     ImageView iov = (ImageView) view.findViewById(R.id.rssi_overlay_image);
                     TextView tv = (TextView) view.findViewById(R.id.rssi_textview);
                     iv.setImageResource(rssiState.signalIconId);
+
                     if (rssiState.dataTypeIconId > 0) {
                         iov.setImageResource(rssiState.dataTypeIconId);
                     } else {
                         iov.setImageDrawable(null);
                     }
                     tv.setText(state.label);
+                    view.setContentDescription(mContext.getResources().getString(
+                            R.string.accessibility_quick_settings_mobile,
+                            rssiState.signalContentDescription, rssiState.dataContentDescription,
+                            state.label));
                 }
             });
             parent.addView(rssiTile);
@@ -460,6 +475,8 @@
                 iv.setImageDrawable(d);
                 iv.setImageLevel(batteryState.batteryLevel);
                 tv.setText(t);
+                view.setContentDescription(
+                        mContext.getString(R.string.accessibility_quick_settings_battery, t));
             }
         });
         parent.addView(batteryTile);
@@ -473,6 +490,12 @@
             public void refreshView(QuickSettingsTileView view, State state) {
                 TextView tv = (TextView) view.findViewById(R.id.airplane_mode_textview);
                 tv.setCompoundDrawablesWithIntrinsicBounds(0, state.iconId, 0, 0);
+
+                String airplaneState = mContext.getString(
+                        (state.enabled) ? R.string.accessibility_desc_on
+                                : R.string.accessibility_desc_off);
+                view.setContentDescription(
+                        mContext.getString(R.string.accessibility_quick_settings_airplane, airplaneState));
                 tv.setText(state.label);
             }
         });
@@ -492,6 +515,7 @@
             mModel.addBluetoothTile(bluetoothTile, new QuickSettingsModel.RefreshCallback() {
                 @Override
                 public void refreshView(QuickSettingsTileView view, State state) {
+                    BluetoothState bluetoothState = (BluetoothState) state;
                     TextView tv = (TextView) view.findViewById(R.id.bluetooth_textview);
                     tv.setCompoundDrawablesWithIntrinsicBounds(0, state.iconId, 0, 0);
 
@@ -510,6 +534,9 @@
                                 btDevices.size());
                     }
                     */
+                    view.setContentDescription(mContext.getString(
+                            R.string.accessibility_quick_settings_bluetooth,
+                            bluetoothState.stateContentDescription));
                     tv.setText(label);
                 }
             });
@@ -561,6 +588,8 @@
                 TextView tv = (TextView) view.findViewById(R.id.alarm_textview);
                 tv.setText(alarmState.label);
                 view.setVisibility(alarmState.enabled ? View.VISIBLE : View.GONE);
+                view.setContentDescription(mContext.getString(
+                        R.string.accessibility_quick_settings_alarm, alarmState.label));
             }
         });
         parent.addView(alarmTile);
@@ -697,7 +726,7 @@
             showBrightnessDialog();
         }
     }
-    
+
     private void removeAllBrightnessDialogCallbacks() {
         mHandler.removeCallbacks(mDismissBrightnessDialogRunnable);
     }
@@ -717,7 +746,7 @@
             mBrightnessDialog.requestWindowFeature(Window.FEATURE_NO_TITLE);
             mBrightnessDialog.setContentView(R.layout.quick_settings_brightness_dialog);
             mBrightnessDialog.setCanceledOnTouchOutside(true);
-        
+
             mBrightnessController = new BrightnessController(mContext,
                     (ToggleSlider) mBrightnessDialog.findViewById(R.id.brightness_slider));
             mBrightnessController.addStateChangedCallback(mModel);
@@ -727,7 +756,7 @@
                     mBrightnessController = null;
                 }
             });
-            
+
             mBrightnessDialog.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT);
             mBrightnessDialog.getWindow().clearFlags(WindowManager.LayoutParams.FLAG_DIM_BEHIND);
         }
@@ -831,6 +860,7 @@
                     Log.e(TAG, "Couldn't get current user id for profile change", e);
                 }
             }
+
         }
     };
 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickSettingsModel.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickSettingsModel.java
index 95cb922..4513dcb 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickSettingsModel.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickSettingsModel.java
@@ -71,7 +71,13 @@
     }
     static class RSSIState extends State {
         int signalIconId;
+        String signalContentDescription;
         int dataTypeIconId;
+        String dataContentDescription;
+    }
+    static class WifiState extends State {
+        String signalContentDescription;
+        boolean connected;
     }
     static class UserState extends State {
         Drawable avatar;
@@ -81,6 +87,7 @@
     }
     public static class BluetoothState extends State {
         boolean connected = false;
+        String stateContentDescription;
     }
 
     /** The callback to update a given tile. */
@@ -182,7 +189,7 @@
 
     private QuickSettingsTileView mWifiTile;
     private RefreshCallback mWifiCallback;
-    private State mWifiState = new State();
+    private WifiState mWifiState = new WifiState();
 
     private QuickSettingsTileView mWifiDisplayTile;
     private RefreshCallback mWifiDisplayCallback;
@@ -371,21 +378,27 @@
     }
     // NetworkSignalChanged callback
     @Override
-    public void onWifiSignalChanged(boolean enabled, int wifiSignalIconId, String enabledDesc) {
+    public void onWifiSignalChanged(boolean enabled, int wifiSignalIconId,
+            String wifiSignalContentDescription, String enabledDesc) {
         // TODO: If view is in awaiting state, disable
         Resources r = mContext.getResources();
-        mWifiState.enabled = enabled;
+
         boolean wifiConnected = enabled && (wifiSignalIconId > 0) && (enabledDesc != null);
         boolean wifiNotConnected = (wifiSignalIconId > 0) && (enabledDesc == null);
+        mWifiState.enabled = enabled;
+        mWifiState.connected = wifiConnected;
         if (wifiConnected) {
             mWifiState.iconId = wifiSignalIconId;
             mWifiState.label = removeDoubleQuotes(enabledDesc);
+            mWifiState.signalContentDescription = wifiSignalContentDescription;
         } else if (wifiNotConnected) {
             mWifiState.iconId = R.drawable.ic_qs_wifi_0;
             mWifiState.label = r.getString(R.string.quick_settings_wifi_label);
+            mWifiState.signalContentDescription = r.getString(R.string.accessibility_no_wifi);
         } else {
             mWifiState.iconId = R.drawable.ic_qs_wifi_no_network;
             mWifiState.label = r.getString(R.string.quick_settings_wifi_off_label);
+            mWifiState.signalContentDescription = r.getString(R.string.accessibility_wifi_off);
         }
         mWifiCallback.refreshView(mWifiTile, mWifiState);
     }
@@ -402,17 +415,24 @@
     }
     // NetworkSignalChanged callback
     @Override
-    public void onMobileDataSignalChanged(boolean enabled, int mobileSignalIconId,
-            int dataTypeIconId, String enabledDesc) {
+    public void onMobileDataSignalChanged(
+            boolean enabled, int mobileSignalIconId, String signalContentDescription,
+            int dataTypeIconId, String dataContentDescription, String enabledDesc) {
         if (deviceSupportsTelephony()) {
             // TODO: If view is in awaiting state, disable
             Resources r = mContext.getResources();
             mRSSIState.signalIconId = enabled && (mobileSignalIconId > 0)
                     ? mobileSignalIconId
                     : R.drawable.ic_qs_signal_no_signal;
+            mRSSIState.signalContentDescription = enabled && (mobileSignalIconId > 0)
+                    ? signalContentDescription
+                    : r.getString(R.string.accessibility_no_signal);
             mRSSIState.dataTypeIconId = enabled && (dataTypeIconId > 0) && !mWifiState.enabled
                     ? dataTypeIconId
                     : 0;
+            mRSSIState.dataContentDescription = enabled && (dataTypeIconId > 0) && !mWifiState.enabled
+                    ? dataContentDescription
+                    : r.getString(R.string.accessibility_no_data);
             mRSSIState.label = enabled
                     ? removeTrailingPeriod(enabledDesc)
                     : r.getString(R.string.quick_settings_rssi_emergency_only);
@@ -448,13 +468,16 @@
         if (mBluetoothState.enabled) {
             if (mBluetoothState.connected) {
                 mBluetoothState.iconId = R.drawable.ic_qs_bluetooth_on;
+                mBluetoothState.stateContentDescription = r.getString(R.string.accessibility_desc_connected);
             } else {
                 mBluetoothState.iconId = R.drawable.ic_qs_bluetooth_not_connected;
+                mBluetoothState.stateContentDescription = r.getString(R.string.accessibility_desc_on);
             }
             mBluetoothState.label = r.getString(R.string.quick_settings_bluetooth_label);
         } else {
             mBluetoothState.iconId = R.drawable.ic_qs_bluetooth_off;
             mBluetoothState.label = r.getString(R.string.quick_settings_bluetooth_off_label);
+            mBluetoothState.stateContentDescription = r.getString(R.string.accessibility_desc_off);
         }
         mBluetoothCallback.refreshView(mBluetoothTile, mBluetoothState);
     }
@@ -632,7 +655,7 @@
                 ? mContext.getString(R.string.quick_settings_rotation_locked_label)
                 : mContext.getString(R.string.quick_settings_rotation_unlocked_label);
 
-        // may be called before addRotationLockTile due to RotationPolicyListener in QuickSettings 
+        // may be called before addRotationLockTile due to RotationPolicyListener in QuickSettings
         if (mRotationLockTile != null && mRotationLockCallback != null) {
             mRotationLockCallback.refreshView(mRotationLockTile, mRotationLockState);
         }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/SettingsPanelView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/SettingsPanelView.java
index e555277..4e10fa3 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/SettingsPanelView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/SettingsPanelView.java
@@ -59,6 +59,8 @@
         mHandleBar = resources.getDrawable(R.drawable.status_bar_close);
         mHandleBarHeight = resources.getDimension(R.dimen.close_handle_height);
         mHandleView = findViewById(R.id.handle);
+
+        setContentDescription(resources.getString(R.string.accessibility_desc_quick_settings));
     }
 
     @Override
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/AccessibilityContentDescriptions.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/AccessibilityContentDescriptions.java
index f45426b..7ac2a98 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/AccessibilityContentDescriptions.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/AccessibilityContentDescriptions.java
@@ -10,7 +10,6 @@
 public class AccessibilityContentDescriptions {
 
     private AccessibilityContentDescriptions() {}
-    
     static final int[] PHONE_SIGNAL_STRENGTH = {
         R.string.accessibility_no_phone,
         R.string.accessibility_phone_one_bar,
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkController.java
index 463aacb..bbb90c8 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkController.java
@@ -174,9 +174,11 @@
     }
 
     public interface NetworkSignalChangedCallback {
-        void onWifiSignalChanged(boolean enabled, int wifiSignalIconId, String description);
-        void onMobileDataSignalChanged(boolean enabled, int mobileSignalIconId, int dataTypeIconId,
-                String description);
+        void onWifiSignalChanged(boolean enabled, int wifiSignalIconId,
+                String wifitSignalContentDescriptionId, String description);
+        void onMobileDataSignalChanged(boolean enabled, int mobileSignalIconId,
+                String mobileSignalContentDescriptionId, int dataTypeIconId,
+                String dataTypeContentDescriptionId, String description);
         void onAirplaneModeChanged(boolean enabled);
     }
 
@@ -347,19 +349,23 @@
         boolean wifiEnabled = mWifiEnabled && (mWifiConnected || !mHasMobileDataFeature);
         String wifiDesc = wifiEnabled ?
                 mWifiSsid : null;
-        cb.onWifiSignalChanged(wifiEnabled, mQSWifiIconId, wifiDesc);
+        cb.onWifiSignalChanged(wifiEnabled, mQSWifiIconId, mContentDescriptionWifi, wifiDesc);
 
         if (isEmergencyOnly()) {
-            cb.onMobileDataSignalChanged(false, mQSPhoneSignalIconId, mQSDataTypeIconId, null);
+            cb.onMobileDataSignalChanged(false, mQSPhoneSignalIconId,
+                    mContentDescriptionPhoneSignal, mQSDataTypeIconId, mContentDescriptionDataType,
+                    null);
         } else {
             if (mIsWimaxEnabled && mWimaxConnected) {
                 // Wimax is special
-                cb.onMobileDataSignalChanged(true, mQSPhoneSignalIconId, mQSDataTypeIconId,
-                        mNetworkName);
+                cb.onMobileDataSignalChanged(true, mQSPhoneSignalIconId,
+                        mContentDescriptionPhoneSignal, mQSDataTypeIconId,
+                        mContentDescriptionDataType, mNetworkName);
             } else {
                 // Normal mobile data
                 cb.onMobileDataSignalChanged(mHasMobileDataFeature, mQSPhoneSignalIconId,
-                        mQSDataTypeIconId, mNetworkName);
+                        mContentDescriptionPhoneSignal, mQSDataTypeIconId,
+                        mContentDescriptionDataType, mNetworkName);
             }
         }
         cb.onAirplaneModeChanged(mAirplaneMode);
@@ -1005,7 +1011,7 @@
             //   - We are connected to mobile data, or
             //   - We are not connected to mobile data, as long as the *reason* packets are not
             //     being routed over that link is that we have better connectivity via wifi.
-            // If data is disconnected for some other reason but wifi (or ethernet/bluetooth) 
+            // If data is disconnected for some other reason but wifi (or ethernet/bluetooth)
             // is connected, we show nothing.
             // Otherwise (nothing connected) we show "No internet connection".
 
@@ -1350,7 +1356,7 @@
 
     public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
         pw.println("NetworkController state:");
-        pw.println(String.format("  %s network type %d (%s)", 
+        pw.println(String.format("  %s network type %d (%s)",
                 mConnected?"CONNECTED":"DISCONNECTED",
                 mConnectedNetworkType, mConnectedNetworkTypeName));
         pw.println("  - telephony ------");