Merge "Polish print settings accessibility." into klp-dev
diff --git a/res/layout/empty_print_state.xml b/res/layout/empty_print_state.xml
index e97bb85..6a82703 100644
--- a/res/layout/empty_print_state.xml
+++ b/res/layout/empty_print_state.xml
@@ -28,7 +28,6 @@
         android:orientation="vertical">
 
         <ImageView
-            android:id="@+id/icon"
             android:layout_width="wrap_content"
             android:layout_height="wrap_content"
             android:layout_marginBottom="12dip"
@@ -41,7 +40,8 @@
             android:layout_width="wrap_content"
             android:layout_height="wrap_content"
             android:textAppearance="?android:attr/textAppearanceLarge"
-            android:textColor="?android:attr/textColorSecondary">
+            android:textColor="?android:attr/textColorSecondary"
+            android:importantForAccessibility="no">
         </TextView>
 
     </LinearLayout>
diff --git a/res/values/strings.xml b/res/values/strings.xml
index 437fa14..71eefe8 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -3483,6 +3483,18 @@
     <!-- Template for the label of the state for a blocked print job. [CHAR LIMIT=25] -->
     <string name="print_blocked_state_title_template">Printer blocked <xliff:g id="print_job_name" example="foo.jpg">%1$s</xliff:g></string>
 
+    <!-- Utterance to announce that the search box is shown. This is spoken to a blind user. [CHAR LIMIT=none] -->
+    <string name="print_search_box_shown_utterance">Search box shown</string>
+
+    <!-- Utterance to announce that the search box is hidden. This is spoken to a blind user. [CHAR LIMIT=none] -->
+    <string name="print_search_box_hidden_utterance">Search box hidden</string>
+
+    <!-- Utterance to announce a change in the number of matches during a search. This is spoken to a blind user. [CHAR LIMIT=none] -->
+    <plurals name="print_search_result_count_utterance">
+        <item quantity="one"><xliff:g id="count" example="1">%1$s</xliff:g> printer found</item>
+        <item quantity="other"><xliff:g id="count" example="2">%1$s</xliff:g> printers found</item>
+    </plurals>
+
     <!-- App Fuel Gauge strings -->
     <skip />
 
diff --git a/src/com/android/settings/accessibility/ToggleFeaturePreferenceFragment.java b/src/com/android/settings/accessibility/ToggleFeaturePreferenceFragment.java
index 171b1ac..2fbbabd 100644
--- a/src/com/android/settings/accessibility/ToggleFeaturePreferenceFragment.java
+++ b/src/com/android/settings/accessibility/ToggleFeaturePreferenceFragment.java
@@ -48,10 +48,6 @@
     protected CharSequence mSettingsTitle;
     protected Intent mSettingsIntent;
 
-    // TODO: Showing sub-sub fragment does not handle the activity title
-    // so we do it but this is wrong. Do a real fix when there is time.
-    private CharSequence mOldActivityTitle;
-
     @Override
     public void onCreate(Bundle savedInstanceState) {
         super.onCreate(savedInstanceState);
@@ -100,9 +96,6 @@
     @Override
     public void onDestroyView() {
         getActivity().getActionBar().setCustomView(null);
-        if (mOldActivityTitle != null) {
-            getActivity().getActionBar().setTitle(mOldActivityTitle);
-        }
         mToggleSwitch.setOnBeforeCheckedChangeListener(null);
         super.onDestroyView();
     }
@@ -144,9 +137,8 @@
         // Title.
         PreferenceActivity activity = (PreferenceActivity) getActivity();
         if (!activity.onIsMultiPane() || activity.onIsHidingHeaders()) {
-            mOldActivityTitle = getActivity().getTitle();
             String title = arguments.getString(AccessibilitySettings.EXTRA_TITLE);
-            getActivity().getActionBar().setTitle(title);
+            getActivity().setTitle(title);
         }
         // Summary.
         CharSequence summary = arguments.getCharSequence(AccessibilitySettings.EXTRA_SUMMARY);
diff --git a/src/com/android/settings/print/PrintJobSettingsFragment.java b/src/com/android/settings/print/PrintJobSettingsFragment.java
index b4d517d..c15bc06 100644
--- a/src/com/android/settings/print/PrintJobSettingsFragment.java
+++ b/src/com/android/settings/print/PrintJobSettingsFragment.java
@@ -78,7 +78,7 @@
                 Context.PRINT_SERVICE)).getGlobalPrintManagerForUser(
                         ActivityManager.getCurrentUser());
 
-        getActivity().getActionBar().setTitle(R.string.print_print_job);
+        getActivity().setTitle(R.string.print_print_job);
 
         processArguments();
 
diff --git a/src/com/android/settings/print/PrintServiceSettingsFragment.java b/src/com/android/settings/print/PrintServiceSettingsFragment.java
index 044d86e..c10f4b9 100644
--- a/src/com/android/settings/print/PrintServiceSettingsFragment.java
+++ b/src/com/android/settings/print/PrintServiceSettingsFragment.java
@@ -55,6 +55,7 @@
 import android.view.ViewGroup;
 import android.widget.BaseAdapter;
 import android.widget.CompoundButton;
+import android.widget.CompoundButton.OnCheckedChangeListener;
 import android.widget.Filter;
 import android.widget.Filterable;
 import android.widget.ImageView;
@@ -71,8 +72,6 @@
 import java.util.LinkedHashMap;
 import java.util.List;
 import java.util.Map;
-
-import android.widget.CompoundButton.OnCheckedChangeListener;
 /**
  * Fragment with print service settings.
  */
@@ -130,14 +129,12 @@
 
     private PrintersAdapter mPrintersAdapter;
 
-    // TODO: Showing sub-sub fragment does not handle the activity title
-    // so we do it but this is wrong. Do a real fix when there is time.
-    private CharSequence mOldActivityTitle;
-
     private int mLastUnfilteredItemCount;
 
     private boolean mServiceEnabled;
 
+    private AnnounceFilterResult mAnnounceFilterResult;
+
     @Override
     public void onResume() {
         super.onResume();
@@ -149,6 +146,9 @@
     @Override
     public void onPause() {
         mSettingsContentObserver.unregister(getContentResolver());
+        if (mAnnounceFilterResult != null) {
+            mAnnounceFilterResult.remove();
+        }
         super.onPause();
     }
 
@@ -162,9 +162,6 @@
     @Override
     public void onDestroyView() {
         getActivity().getActionBar().setCustomView(null);
-        if (mOldActivityTitle != null) {
-            getActivity().getActionBar().setTitle(mOldActivityTitle);
-        }
         mToggleSwitch.setOnBeforeCheckedChangeListener(null);
         super.onDestroyView();
     }
@@ -235,8 +232,7 @@
             if (emptyView == null) {
                 emptyView = getActivity().getLayoutInflater().inflate(
                         R.layout.empty_print_state, contentRoot, false);
-                ImageView iconView = (ImageView) emptyView.findViewById(R.id.icon);
-                iconView.setContentDescription(getString(R.string.print_service_disabled));
+                emptyView.setContentDescription(getString(R.string.print_service_disabled));
                 TextView textView = (TextView) emptyView.findViewById(R.id.message);
                 textView.setText(R.string.print_service_disabled);
                 contentRoot.addView(emptyView);
@@ -262,8 +258,7 @@
             if (emptyView == null) {
                 emptyView = getActivity().getLayoutInflater().inflate(
                         R.layout.empty_print_state, contentRoot, false);
-                ImageView iconView = (ImageView) emptyView.findViewById(R.id.icon);
-                iconView.setContentDescription(getString(R.string.print_no_printers_found));
+                emptyView.setContentDescription(getString(R.string.print_no_printers_found));
                 TextView textView = (TextView) emptyView.findViewById(R.id.message);
                 textView.setText(R.string.print_no_printers_found);
                 contentRoot.addView(emptyView);
@@ -331,9 +326,11 @@
         // Title.
         PreferenceActivity activity = (PreferenceActivity) getActivity();
         if (!activity.onIsMultiPane() || activity.onIsHidingHeaders()) {
-            mOldActivityTitle = getActivity().getTitle();
+            // PreferenceActivity allows passing as an extra only title by its
+            // resource id but we do not have the resource id for the print
+            // service label. Therefore, we do it ourselves.
             String title = arguments.getString(PrintSettingsFragment.EXTRA_TITLE);
-            getActivity().getActionBar().setTitle(title);
+            getActivity().setTitle(title);
         }
 
         // Settings title and intent.
@@ -425,6 +422,18 @@
                     return true;
                 }
             });
+            searchView.addOnAttachStateChangeListener(new View.OnAttachStateChangeListener() {
+                @Override
+                public void onViewAttachedToWindow(View view) {
+                    view.announceForAccessibility(getString(
+                            R.string.print_search_box_shown_utterance));
+                }
+                @Override
+                public void onViewDetachedFromWindow(View view) {
+                    view.announceForAccessibility(getString(
+                            R.string.print_search_box_hidden_utterance));
+                }
+            });
         } else {
             menu.removeItem(R.id.print_menu_item_search);
         }
@@ -463,6 +472,39 @@
         public abstract void onChange(boolean selfChange, Uri uri);
     }
 
+    private final class AnnounceFilterResult implements Runnable {
+        private static final int SEARCH_RESULT_ANNOUNCEMENT_DELAY = 1000; // 1 sec
+
+        public void post() {
+            remove();
+            getListView().postDelayed(this, SEARCH_RESULT_ANNOUNCEMENT_DELAY);
+        }
+
+        public void remove() {
+            getListView().removeCallbacks(this);
+        }
+
+        @Override
+        public void run() {
+            final int count = getListView().getAdapter().getCount();
+            final String text;
+            if (count <= 0) {
+                text = getString(R.string.print_no_printers_found);
+            } else {
+                text = getActivity().getResources().getQuantityString(
+                    R.plurals.print_search_result_count_utterance, count, count);
+            }
+            getListView().announceForAccessibility(text);
+        }
+    }
+
+    private void announceSearchResult() {
+        if (mAnnounceFilterResult == null) {
+            mAnnounceFilterResult = new AnnounceFilterResult();
+        }
+        mAnnounceFilterResult.post();
+    }
+
     private final class PrintersAdapter extends BaseAdapter
             implements LoaderManager.LoaderCallbacks<List<PrinterInfo>>, Filterable {
         private final Object mLock = new Object();
@@ -514,7 +556,9 @@
                 @Override
                 @SuppressWarnings("unchecked")
                 protected void publishResults(CharSequence constraint, FilterResults results) {
+                    final boolean resultCountChanged;
                     synchronized (mLock) {
+                        final int oldPrinterCount = mFilteredPrinters.size();
                         mLastSearchString = constraint;
                         mFilteredPrinters.clear();
                         if (results == null) {
@@ -523,6 +567,10 @@
                             List<PrinterInfo> printers = (List<PrinterInfo>) results.values;
                             mFilteredPrinters.addAll(printers);
                         }
+                        resultCountChanged = (oldPrinterCount != mFilteredPrinters.size());
+                    }
+                    if (resultCountChanged) {
+                        announceSearchResult();
                     }
                     notifyDataSetChanged();
                 }