Merge "Import translations. DO NOT MERGE" 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 9c5d039..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 />
@@ -3631,7 +3643,7 @@
<!-- Suggestion for exploring application info to stop or uninstall -->
<string name="battery_sugg_apps_info">Stop or uninstall the app</string>
<!-- [CHAR LIMIT=100] Suggestion for getting apps to consume less power due to GPS-->
- <string name="battery_sugg_apps_gps">"Manually control GPS to prevent app from using it"</string>
+ <string name="battery_sugg_apps_gps">Select battery-saving mode</string>
<!-- Suggestion for getting apps to consume less power -->
<string name="battery_sugg_apps_settings">The app may offer settings to reduce battery use</string>
@@ -4768,6 +4780,8 @@
<!-- Home application selection - uninstall button [CHAR LIMIT=80] -->
<string name="home_app_uninstall_button">Uninstall this application</string>
+ <!-- Message to user that Home Settings will be hidden because there is now only one available home application -->
+ <string name="only_one_home_message">Home settings will be hidden until you install another home application.</string>
<!-- Warning message when changing a global setting for a tablet.[CHAR LIMIT=none] -->
<string name="global_change_warning" product="tablet">This setting affects all users on this tablet.</string>
diff --git a/src/com/android/settings/HomeSettings.java b/src/com/android/settings/HomeSettings.java
index bac94d6..14e1d9f 100644
--- a/src/com/android/settings/HomeSettings.java
+++ b/src/com/android/settings/HomeSettings.java
@@ -23,6 +23,7 @@
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
+import android.content.SharedPreferences;
import android.content.pm.ActivityInfo;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageInfo;
@@ -50,6 +51,8 @@
public static final String CURRENT_HOME = "current_home";
+ public static final String HOME_SHOW_NOTICE = "show";
+
PreferenceGroup mPrefGroup;
PackageManager mPm;
@@ -57,6 +60,7 @@
ArrayList<HomeAppPreference> mPrefs;
HomeAppPreference mCurrentHome = null;
final IntentFilter mHomeFilter;
+ boolean mShowNotice;
public HomeSettings() {
mHomeFilter = new IntentFilter(Intent.ACTION_MAIN);
@@ -126,6 +130,17 @@
}
}
}
+
+ // If we're down to just one possible home app, back out of this settings
+ // fragment and show a dialog explaining to the user that they won't see
+ // 'Home' settings now until such time as there are multiple available.
+ if (mPrefs.size() < 2) {
+ if (mShowNotice) {
+ mShowNotice = false;
+ Settings.requestHomeNotice();
+ }
+ finishFragment();
+ }
}
void buildHomeActivitiesList() {
@@ -176,6 +191,9 @@
mPm = getPackageManager();
mPrefGroup = (PreferenceGroup) findPreference("home");
+
+ Bundle args = getArguments();
+ mShowNotice = (args != null) && args.getBoolean(HOME_SHOW_NOTICE, false);
}
@Override
diff --git a/src/com/android/settings/Settings.java b/src/com/android/settings/Settings.java
index 87d34c6..eb98fec 100644
--- a/src/com/android/settings/Settings.java
+++ b/src/com/android/settings/Settings.java
@@ -19,6 +19,10 @@
import android.accounts.Account;
import android.accounts.AccountManager;
import android.accounts.OnAccountsUpdateListener;
+import android.app.Activity;
+import android.app.AlertDialog;
+import android.app.Dialog;
+import android.app.DialogFragment;
import android.app.admin.DevicePolicyManager;
import android.content.BroadcastReceiver;
import android.content.ComponentName;
@@ -27,7 +31,6 @@
import android.content.IntentFilter;
import android.content.SharedPreferences;
import android.content.pm.ActivityInfo;
-import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
import android.content.pm.ResolveInfo;
@@ -117,6 +120,10 @@
private static final String SAVE_KEY_CURRENT_HEADER = "com.android.settings.CURRENT_HEADER";
private static final String SAVE_KEY_PARENT_HEADER = "com.android.settings.PARENT_HEADER";
+ static final int DIALOG_ONLY_ONE_HOME = 1;
+
+ private static boolean sShowNoHomeNotice = false;
+
private String mFragmentClass;
private int mTopLevelHeaderId;
private Header mFirstHeader;
@@ -516,8 +523,10 @@
*/
@Override
public void onBuildHeaders(List<Header> headers) {
- loadHeadersFromResource(R.xml.settings_headers, headers);
- updateHeaderList(headers);
+ if (!onIsHidingHeaders()) {
+ loadHeadersFromResource(R.xml.settings_headers, headers);
+ updateHeaderList(headers);
+ }
}
private void updateHeaderList(List<Header> target) {
@@ -655,6 +664,7 @@
}
}
accountHeaders.add(accHeader);
+ mAuthenticatorHelper.preloadDrawableForType(this, accountType);
}
// Sort by label
@@ -681,8 +691,22 @@
getPackageManager().getHomeActivities(homeApps);
if (homeApps.size() < 2) {
// When there's only one available home app, omit this settings
- // category entirely at the top level UI.
+ // category entirely at the top level UI. If the user just
+ // uninstalled the penultimate home app candidiate, we also
+ // now tell them about why they aren't seeing 'Home' in the list.
+ if (sShowNoHomeNotice) {
+ sShowNoHomeNotice = false;
+ NoHomeDialogFragment.show(this);
+ }
return false;
+ } else {
+ // Okay, we're allowing the Home settings category. Tell it, when
+ // invoked via this front door, that we'll need to be told about the
+ // case when the user uninstalls all but one home app.
+ if (header.fragmentArguments == null) {
+ header.fragmentArguments = new Bundle();
+ }
+ header.fragmentArguments.putBoolean(HomeSettings.HOME_SHOW_NOTICE, true);
}
} catch (Exception e) {
// Can't look up the home activity; bail on configuring the icon
@@ -724,6 +748,21 @@
return super.getNextButton();
}
+ public static class NoHomeDialogFragment extends DialogFragment {
+ public static void show(Activity parent) {
+ final NoHomeDialogFragment dialog = new NoHomeDialogFragment();
+ dialog.show(parent.getFragmentManager(), null);
+ }
+
+ @Override
+ public Dialog onCreateDialog(Bundle savedInstanceState) {
+ return new AlertDialog.Builder(getActivity())
+ .setMessage(R.string.only_one_home_message)
+ .setPositiveButton(android.R.string.ok, null)
+ .create();
+ }
+ }
+
private static class HeaderAdapter extends ArrayAdapter<Header> {
static final int HEADER_TYPE_CATEGORY = 0;
static final int HEADER_TYPE_NORMAL = 1;
@@ -915,11 +954,6 @@
ManageAccountsSettings.KEY_ACCOUNT_TYPE);
Drawable icon = mAuthHelper.getDrawableForType(getContext(), accType);
setHeaderIcon(holder, icon);
- } else if (header.extras != null &&
- header.extras.containsKey(HomeSettings.CURRENT_HOME)) {
- ActivityInfo ai = header.extras.getParcelable(HomeSettings.CURRENT_HOME);
- Drawable icon = ai.loadIcon(getContext().getPackageManager());
- setHeaderIcon(holder, icon);
} else {
holder.icon.setImageResource(header.iconRes);
}
@@ -1012,6 +1046,10 @@
invalidateHeaders();
}
+ public static void requestHomeNotice() {
+ sShowNoHomeNotice = true;
+ }
+
/*
* Settings subclasses for launching independently.
*/
diff --git a/src/com/android/settings/WirelessSettings.java b/src/com/android/settings/WirelessSettings.java
index 756705d..6724cc1 100644
--- a/src/com/android/settings/WirelessSettings.java
+++ b/src/com/android/settings/WirelessSettings.java
@@ -247,12 +247,7 @@
private boolean isSmsSupported() {
// Some tablet has sim card but could not do telephony operations. Skip those.
- if (mTm.getPhoneType() == TelephonyManager.PHONE_TYPE_NONE) {
- return false;
- }
- int simState = mTm.getSimState();
- return simState != TelephonyManager.SIM_STATE_ABSENT &&
- simState != TelephonyManager.SIM_STATE_UNKNOWN;
+ return (mTm.getPhoneType() != TelephonyManager.PHONE_TYPE_NONE);
}
@Override
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/accounts/AuthenticatorHelper.java b/src/com/android/settings/accounts/AuthenticatorHelper.java
index eba785b..a164b8b 100644
--- a/src/com/android/settings/accounts/AuthenticatorHelper.java
+++ b/src/com/android/settings/accounts/AuthenticatorHelper.java
@@ -23,6 +23,7 @@
import android.content.pm.PackageManager;
import android.content.res.Resources;
import android.graphics.drawable.Drawable;
+import android.os.AsyncTask;
import android.util.Log;
import java.util.ArrayList;
@@ -45,6 +46,16 @@
return mEnabledAccountTypes.toArray(new String[mEnabledAccountTypes.size()]);
}
+ public void preloadDrawableForType(final Context context, final String accountType) {
+ new AsyncTask<Void, Void, Void>() {
+ @Override
+ protected Void doInBackground(Void... params) {
+ getDrawableForType(context, accountType);
+ return null;
+ }
+ }.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, (Void[]) null);
+ }
+
/**
* Gets an icon associated with a particular account type. If none found, return null.
* @param accountType the type of account
@@ -52,15 +63,19 @@
*/
public Drawable getDrawableForType(Context context, final String accountType) {
Drawable icon = null;
- if (mAccTypeIconCache.containsKey(accountType)) {
- return mAccTypeIconCache.get(accountType);
+ synchronized (mAccTypeIconCache) {
+ if (mAccTypeIconCache.containsKey(accountType)) {
+ return mAccTypeIconCache.get(accountType);
+ }
}
if (mTypeToAuthDescription.containsKey(accountType)) {
try {
AuthenticatorDescription desc = mTypeToAuthDescription.get(accountType);
Context authContext = context.createPackageContext(desc.packageName, 0);
icon = authContext.getResources().getDrawable(desc.iconId);
- mAccTypeIconCache.put(accountType, icon);
+ synchronized (mAccTypeIconCache) {
+ mAccTypeIconCache.put(accountType, icon);
+ }
} catch (PackageManager.NameNotFoundException e) {
} catch (Resources.NotFoundException e) {
}
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();
}