OSDN Git Service

merge in klp-release history after reset to klp-dev
authorThe Android Automerger <android-build@google.com>
Thu, 22 Aug 2013 13:01:56 +0000 (06:01 -0700)
committerThe Android Automerger <android-build@google.com>
Thu, 22 Aug 2013 13:01:56 +0000 (06:01 -0700)
14 files changed:
res/layout/captioning_preview.xml
res/layout/preset_picker_item.xml
res/values/arrays.xml
src/com/android/settings/DevelopmentSettings.java
src/com/android/settings/accessibility/CaptioningTextView.java [deleted file]
src/com/android/settings/accessibility/EdgeTypePreference.java
src/com/android/settings/accessibility/PresetPreference.java
src/com/android/settings/accessibility/ToggleCaptioningPreferenceFragment.java
src/com/android/settings/location/LocationMode.java
src/com/android/settings/location/LocationSettings.java
src/com/android/settings/location/LocationSettingsBase.java
src/com/android/settings/location/RecentLocationApps.java
src/com/android/settings/location/SettingsInjector.java
src/com/android/settings/widget/SettingsAppWidgetProvider.java

index b2e16fa..00d94a0 100644 (file)
@@ -31,7 +31,7 @@
             android:scaleType="centerCrop"
             android:src="@drawable/caption_background" />
 
-        <com.android.settings.accessibility.CaptioningTextView
+        <com.android.internal.widget.SubtitleView
             android:id="@+id/preview_text"
             android:layout_width="wrap_content"
             android:layout_height="wrap_content"
index 1b66970..9d799ef 100644 (file)
@@ -25,7 +25,7 @@
         android:layout_height="96dp"
         android:background="@drawable/transparency_tileable" >
 
-        <com.android.settings.accessibility.CaptioningTextView
+        <com.android.internal.widget.SubtitleView
             android:id="@+id/preview"
             android:layout_width="wrap_content"
             android:layout_height="wrap_content"
index e58107a..20f759d 100644 (file)
         <item>true</item>
     </string-array>
 
-    <!-- Titles for debug overdraw preference. [CHAR LIMIT=35] -->
+    <!-- Titles for debug overdraw preference. [CHAR LIMIT=50] -->
     <string-array name="debug_hw_overdraw_entries">
         <item>Off</item>
         <item>Show overdraw areas</item>
+        <item>Show areas for Deuteranomaly</item>
         <item>Show overdraw counter</item>
     </string-array>
 
     <string-array name="debug_hw_overdraw_values" translatable="false" >
         <item>false</item>
         <item>show</item>
+        <item>show_deuteranomaly</item>
         <item>count</item>
     </string-array>
 
index 11ffbf7..1578e4e 100644 (file)
@@ -1135,6 +1135,14 @@ public class DevelopmentSettings extends RestrictedSettingsFragment
 
     private void writeExperimentalWebViewOptions() {
         if (mExperimentalWebView != null) {
+            if (!WebViewFactory.isUseExperimentalWebViewSet()) {
+                    mEnableDialog = new AlertDialog.Builder(getActivity())
+                            .setTitle("KLP WebView broke an app?")
+                            .setMessage("Don't forget to raise a bug!\ngo/klp-webview-bug")
+                            .setIconAttribute(android.R.attr.alertDialogIcon)
+                            .setPositiveButton(android.R.string.ok, this)
+                            .show();
+            }
             WebViewFactory.setUseExperimentalWebView(mExperimentalWebView.isChecked());
             pokeSystemProperties();
         }
diff --git a/src/com/android/settings/accessibility/CaptioningTextView.java b/src/com/android/settings/accessibility/CaptioningTextView.java
deleted file mode 100644 (file)
index d720e8f..0000000
+++ /dev/null
@@ -1,370 +0,0 @@
-/*
- * Copyright (C) 2013 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.settings.accessibility;
-
-import android.content.ContentResolver;
-import android.content.Context;
-import android.content.res.Resources.Theme;
-import android.content.res.TypedArray;
-import android.graphics.Canvas;
-import android.graphics.Color;
-import android.graphics.Paint;
-import android.graphics.Paint.Join;
-import android.graphics.Paint.Style;
-import android.graphics.RectF;
-import android.graphics.Typeface;
-import android.text.Layout.Alignment;
-import android.text.StaticLayout;
-import android.text.TextPaint;
-import android.text.TextUtils;
-import android.util.AttributeSet;
-import android.util.DisplayMetrics;
-import android.util.TypedValue;
-import android.view.View;
-import android.view.accessibility.CaptioningManager.CaptionStyle;
-
-public class CaptioningTextView extends View {
-    // Ratio of inner padding to font size.
-    private static final float INNER_PADDING_RATIO = 0.125f;
-
-    // Default style dimensions in dips.
-    private static final float CORNER_RADIUS = 2.0f;
-    private static final float OUTLINE_WIDTH = 2.0f;
-    private static final float SHADOW_RADIUS = 2.0f;
-    private static final float SHADOW_OFFSET_X = 2.0f;
-    private static final float SHADOW_OFFSET_Y = 2.0f;
-
-    // Styled dimensions.
-    private final float mCornerRadius;
-    private final float mOutlineWidth;
-    private final float mShadowRadius;
-    private final float mShadowOffsetX;
-    private final float mShadowOffsetY;
-
-    /** Temporary rectangle used for computing line bounds. */
-    private final RectF mLineBounds = new RectF();
-
-    /** Temporary array used for computing line wrapping. */
-    private float[] mTextWidths;
-
-    /** Reusable string builder used for holding text. */
-    private final StringBuilder mText = new StringBuilder();
-    private final StringBuilder mBreakText = new StringBuilder();
-
-    private TextPaint mPaint;
-
-    private int mForegroundColor;
-    private int mBackgroundColor;
-    private int mEdgeColor;
-    private int mEdgeType;
-
-    private boolean mHasMeasurements;
-    private int mLastMeasuredWidth;
-    private StaticLayout mLayout;
-
-    private float mSpacingMult = 1;
-    private float mSpacingAdd = 0;
-    private int mInnerPaddingX = 0;
-
-    public CaptioningTextView(Context context, AttributeSet attrs) {
-        this(context, attrs, 0);
-    }
-
-    public CaptioningTextView(Context context, AttributeSet attrs, int defStyle) {
-        super(context, attrs);
-
-        final Theme theme = context.getTheme();
-        final TypedArray a = theme.obtainStyledAttributes(
-                    attrs, android.R.styleable.TextView, defStyle, 0);
-
-        CharSequence text = "";
-        int textSize = 15;
-
-        final int n = a.getIndexCount();
-        for (int i = 0; i < n; i++) {
-            int attr = a.getIndex(i);
-
-            switch (attr) {
-                case android.R.styleable.TextView_text:
-                    text = a.getText(attr);
-                    break;
-                case android.R.styleable.TextView_lineSpacingExtra:
-                    mSpacingAdd = a.getDimensionPixelSize(attr, (int) mSpacingAdd);
-                    break;
-                case android.R.styleable.TextView_lineSpacingMultiplier:
-                    mSpacingMult = a.getFloat(attr, mSpacingMult);
-                    break;
-                case android.R.styleable.TextAppearance_textSize:
-                    textSize = a.getDimensionPixelSize(attr, textSize);
-                    break;
-            }
-        }
-
-        // Set up density-dependent properties.
-        // TODO: Move these to a default style.
-        final DisplayMetrics m = getContext().getResources().getDisplayMetrics();
-        mCornerRadius = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, CORNER_RADIUS, m);
-        mOutlineWidth = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, OUTLINE_WIDTH, m);
-        mShadowRadius = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, SHADOW_RADIUS, m);
-        mShadowOffsetX = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, SHADOW_OFFSET_Y, m);
-        mShadowOffsetY = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, SHADOW_OFFSET_X, m);
-
-        final TextPaint paint = new TextPaint();
-        paint.setAntiAlias(true);
-        paint.setSubpixelText(true);
-
-        mPaint = paint;
-
-        setText(text);
-        setTextSize(textSize);
-    }
-
-    public void setText(int resId) {
-        final CharSequence text = getContext().getText(resId);
-        setText(text);
-    }
-
-    public void setText(CharSequence text) {
-        mText.setLength(0);
-        mText.append(text);
-
-        mHasMeasurements = false;
-
-        requestLayout();
-    }
-
-    public void setForegroundColor(int color) {
-        mForegroundColor = color;
-
-        invalidate();
-    }
-
-    @Override
-    public void setBackgroundColor(int color) {
-        mBackgroundColor = color;
-
-        invalidate();
-    }
-
-    public void setEdgeType(int edgeType) {
-        mEdgeType = edgeType;
-
-        invalidate();
-    }
-
-    public void setEdgeColor(int color) {
-        mEdgeColor = color;
-
-        invalidate();
-    }
-
-    public void setTextSize(float size) {
-        final DisplayMetrics metrics = getContext().getResources().getDisplayMetrics();
-        final float pixels = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP, size, metrics);
-        if (mPaint.getTextSize() != size) {
-            mHasMeasurements = false;
-            mInnerPaddingX = (int) (size * INNER_PADDING_RATIO + 0.5f);
-            mPaint.setTextSize(size);
-
-            requestLayout();
-        }
-    }
-
-    public void setTypeface(Typeface typeface) {
-        if (mPaint.getTypeface() != typeface) {
-            mHasMeasurements = false;
-            mPaint.setTypeface(typeface);
-
-            requestLayout();
-        }
-    }
-
-    @Override
-    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
-        final int widthSpec = MeasureSpec.getSize(widthMeasureSpec);
-
-        if (computeMeasurements(widthSpec)) {
-            final StaticLayout layout = mLayout;
-
-            // Account for padding.
-            final int paddingX = mPaddingLeft + mPaddingRight + mInnerPaddingX * 2;
-            final int width = layout.getWidth() + paddingX;
-            final int height = layout.getHeight() + mPaddingTop + mPaddingBottom;
-            setMeasuredDimension(width, height);
-        } else {
-            setMeasuredDimension(MEASURED_STATE_TOO_SMALL, MEASURED_STATE_TOO_SMALL);
-        }
-    }
-
-    @Override
-    public void onLayout(boolean changed, int l, int t, int r, int b) {
-        final int width = r - l;
-
-        computeMeasurements(width);
-    }
-
-    private boolean computeMeasurements(int maxWidth) {
-        if (mHasMeasurements && maxWidth == mLastMeasuredWidth) {
-            return true;
-        }
-
-        // Account for padding.
-        final int paddingX = mPaddingLeft + mPaddingRight + mInnerPaddingX;
-        maxWidth -= paddingX;
-
-        if (maxWidth <= 0) {
-            return false;
-        }
-
-        final TextPaint paint = mPaint;
-        final CharSequence text = mText;
-        final int textLength = text.length();
-        if (mTextWidths == null || mTextWidths.length < textLength) {
-            mTextWidths = new float[textLength];
-        }
-
-        final float[] textWidths = mTextWidths;
-        paint.getTextWidths(text, 0, textLength, textWidths);
-
-        // Compute total length.
-        float runLength = 0;
-        for (int i = 0; i < textLength; i++) {
-            runLength += textWidths[i];
-        }
-
-        final int lineCount = (int) (runLength / maxWidth) + 1;
-        final int lineLength = (int) (runLength / lineCount);
-
-        // Build line break buffer.
-        final StringBuilder breakText = mBreakText;
-        breakText.setLength(0);
-
-        int line = 0;
-        int lastBreak = 0;
-        int maxRunLength = 0;
-        runLength = 0;
-        for (int i = 0; i < textLength; i++) {
-            if (runLength > lineLength) {
-                final CharSequence sequence = text.subSequence(lastBreak, i);
-                final int trimmedLength = TextUtils.getTrimmedLength(sequence);
-                breakText.append(sequence, 0, trimmedLength);
-                breakText.append('\n');
-                lastBreak = i;
-                runLength = 0;
-            }
-
-            runLength += textWidths[i];
-
-            if (runLength > maxRunLength) {
-                maxRunLength = (int) Math.ceil(runLength);
-            }
-        }
-        breakText.append(text.subSequence(lastBreak, textLength));
-
-        mHasMeasurements = true;
-        mLastMeasuredWidth = maxWidth;
-
-        mLayout = new StaticLayout(breakText, paint, maxRunLength, Alignment.ALIGN_LEFT,
-                mSpacingMult, mSpacingAdd, true);
-
-        return true;
-    }
-
-    public void setStyle(int styleId) {
-        final Context context = mContext;
-        final ContentResolver cr = context.getContentResolver();
-        final CaptionStyle style;
-        if (styleId == CaptionStyle.PRESET_CUSTOM) {
-            style = CaptionStyle.getCustomStyle(cr);
-        } else {
-            style = CaptionStyle.PRESETS[styleId];
-        }
-
-        mForegroundColor = style.foregroundColor;
-        mBackgroundColor = style.backgroundColor;
-        mEdgeType = style.edgeType;
-        mEdgeColor = style.edgeColor;
-        mHasMeasurements = false;
-
-        final Typeface typeface = style.getTypeface();
-        setTypeface(typeface);
-
-        requestLayout();
-    }
-
-    @Override
-    protected void onDraw(Canvas c) {
-        final StaticLayout layout = mLayout;
-        if (layout == null) {
-            return;
-        }
-
-        final int saveCount = c.save();
-        final int innerPaddingX = mInnerPaddingX;
-        c.translate(mPaddingLeft + innerPaddingX, mPaddingTop);
-
-        final RectF bounds = mLineBounds;
-        final int lineCount = layout.getLineCount();
-        final Paint paint = layout.getPaint();
-        paint.setShadowLayer(0, 0, 0, 0);
-
-        final int backgroundColor = mBackgroundColor;
-        if (Color.alpha(backgroundColor) > 0) {
-            paint.setColor(backgroundColor);
-            paint.setStyle(Style.FILL);
-
-            final float cornerRadius = mCornerRadius;
-            float previousBottom = layout.getLineTop(0);
-
-            for (int i = 0; i < lineCount; i++) {
-                bounds.left = layout.getLineLeft(i) - innerPaddingX;
-                bounds.right = layout.getLineRight(i) + innerPaddingX;
-                bounds.top = previousBottom;
-                bounds.bottom = layout.getLineBottom(i);
-
-                previousBottom = bounds.bottom;
-
-                c.drawRoundRect(bounds, cornerRadius, cornerRadius, paint);
-            }
-        }
-
-        final int edgeType = mEdgeType;
-        if (edgeType == CaptionStyle.EDGE_TYPE_OUTLINE) {
-            paint.setColor(mEdgeColor);
-            paint.setStyle(Style.FILL_AND_STROKE);
-            paint.setStrokeJoin(Join.ROUND);
-            paint.setStrokeWidth(mOutlineWidth);
-
-            for (int i = 0; i < lineCount; i++) {
-                layout.drawText(c, i, i);
-            }
-        }
-
-        if (edgeType == CaptionStyle.EDGE_TYPE_DROP_SHADOW) {
-            paint.setShadowLayer(mShadowRadius, mShadowOffsetX, mShadowOffsetY, mEdgeColor);
-        }
-
-        paint.setColor(mForegroundColor);
-        paint.setStyle(Style.FILL);
-
-        for (int i = 0; i < lineCount; i++) {
-            layout.drawText(c, i, i);
-        }
-
-        c.restoreToCount(saveCount);
-    }
-}
index d146960..1d73e6c 100644 (file)
@@ -25,6 +25,7 @@ import android.view.accessibility.CaptioningManager;
 import android.view.accessibility.CaptioningManager.CaptionStyle;
 import android.widget.TextView;
 
+import com.android.internal.widget.SubtitleView;
 import com.android.settings.R;
 
 /**
@@ -49,7 +50,7 @@ public class EdgeTypePreference extends ListDialogPreference {
     @Override
     protected void onBindListItem(View view, int index) {
         final float fontSize = CaptioningManager.getFontSize(getContext().getContentResolver());
-        final CaptioningTextView preview = (CaptioningTextView) view.findViewById(R.id.preview);
+        final SubtitleView preview = (SubtitleView) view.findViewById(R.id.preview);
 
         preview.setForegroundColor(Color.WHITE);
         preview.setBackgroundColor(Color.TRANSPARENT);
index cd01082..9ac7ef8 100644 (file)
@@ -22,6 +22,7 @@ import android.view.View;
 import android.view.accessibility.CaptioningManager.CaptionStyle;
 import android.widget.TextView;
 
+import com.android.internal.widget.SubtitleView;
 import com.android.settings.R;
 
 public class PresetPreference extends ListDialogPreference {
@@ -40,8 +41,7 @@ public class PresetPreference extends ListDialogPreference {
 
     @Override
     protected void onBindListItem(View view, int index) {
-        final CaptioningTextView previewText = (CaptioningTextView) view.findViewById(
-                R.id.preview);
+        final SubtitleView previewText = (SubtitleView) view.findViewById(R.id.preview);
         final int value = getValueAt(index);
         ToggleCaptioningPreferenceFragment.applyCaptionProperties(previewText, value);
 
index e248d14..a0835d2 100644 (file)
@@ -31,6 +31,7 @@ import android.view.ViewGroup;
 import android.view.accessibility.CaptioningManager;
 import android.view.accessibility.CaptioningManager.CaptionStyle;
 
+import com.android.internal.widget.SubtitleView;
 import com.android.settings.R;
 import com.android.settings.accessibility.ToggleSwitch.OnBeforeCheckedChangeListener;
 
@@ -38,7 +39,7 @@ import java.util.Locale;
 
 public class ToggleCaptioningPreferenceFragment extends Fragment {
     private CaptionPropertiesFragment mPropsFragment;
-    private CaptioningTextView mPreviewText;
+    private SubtitleView mPreviewText;
 
     @Override
     public View onCreateView(
@@ -62,14 +63,14 @@ public class ToggleCaptioningPreferenceFragment extends Fragment {
                 .findFragmentById(R.id.properties_fragment));
         mPropsFragment.setParent(this);
 
-        mPreviewText = (CaptioningTextView) view.findViewById(R.id.preview_text);
+        mPreviewText = (SubtitleView) view.findViewById(R.id.preview_text);
 
         installActionBarToggleSwitch();
         refreshPreviewText();
     }
 
     public void refreshPreviewText() {
-        final CaptioningTextView preview = mPreviewText;
+        final SubtitleView preview = mPreviewText;
         if (preview != null) {
             final Activity activity = getActivity();
             final ContentResolver cr = activity.getContentResolver();
@@ -85,7 +86,7 @@ public class ToggleCaptioningPreferenceFragment extends Fragment {
         }
     }
 
-    public static void applyCaptionProperties(CaptioningTextView previewText, int styleId) {
+    public static void applyCaptionProperties(SubtitleView previewText, int styleId) {
         previewText.setStyle(styleId);
 
         final Context context = previewText.getContext();
index 7001126..70cee99 100644 (file)
@@ -20,6 +20,7 @@ import android.app.Activity;
 import android.content.Intent;
 import android.preference.PreferenceActivity;
 import android.preference.PreferenceScreen;
+import android.provider.Settings;
 
 import com.android.settings.R;
 
@@ -97,13 +98,13 @@ public class LocationMode extends LocationSettingsBase
 
     @Override
     public void onRadioButtonClicked(RadioButtonPreference emiter) {
-        int mode = LocationSettingsBase.MODE_LOCATION_OFF;
+        int mode = Settings.Secure.LOCATION_MODE_OFF;
         if (emiter == mHighAccuracy) {
-            mode = LocationSettingsBase.MODE_HIGH_ACCURACY;
+            mode = Settings.Secure.LOCATION_MODE_HIGH_ACCURACY;
         } else if (emiter == mBatterySaving) {
-            mode = LocationSettingsBase.MODE_BATTERY_SAVING;
+            mode = Settings.Secure.LOCATION_MODE_BATTERY_SAVING;
         } else if (emiter == mSensorsOnly) {
-            mode = LocationSettingsBase.MODE_SENSORS_ONLY;
+            mode = Settings.Secure.LOCATION_MODE_SENSORS_ONLY;
         }
         setLocationMode(mode);
     }
@@ -111,24 +112,24 @@ public class LocationMode extends LocationSettingsBase
     @Override
     public void onModeChanged(int mode) {
         switch (mode) {
-            case MODE_LOCATION_OFF:
+            case Settings.Secure.LOCATION_MODE_OFF:
                 Intent intent = new Intent();
                 PreferenceActivity pa = (PreferenceActivity) getActivity();
                 pa.finishPreferencePanel(LocationMode.this, Activity.RESULT_OK, intent);
                 break;
-            case MODE_SENSORS_ONLY:
+            case Settings.Secure.LOCATION_MODE_SENSORS_ONLY:
                 updateRadioButtons(mSensorsOnly);
                 break;
-            case MODE_BATTERY_SAVING:
+            case Settings.Secure.LOCATION_MODE_BATTERY_SAVING:
                 updateRadioButtons(mBatterySaving);
                 break;
-            case MODE_HIGH_ACCURACY:
+            case Settings.Secure.LOCATION_MODE_HIGH_ACCURACY:
                 updateRadioButtons(mHighAccuracy);
                 break;
             default:
                 break;
         }
-        boolean enabled = (mode != MODE_LOCATION_OFF);
+        boolean enabled = (mode != Settings.Secure.LOCATION_MODE_OFF);
         mHighAccuracy.setEnabled(enabled);
         mBatterySaving.setEnabled(enabled);
         mSensorsOnly.setEnabled(enabled);
index e349ad4..4970d37 100644 (file)
@@ -23,7 +23,10 @@ import android.os.Bundle;
 import android.preference.Preference;
 import android.preference.PreferenceActivity;
 import android.preference.PreferenceCategory;
+import android.preference.PreferenceGroup;
+import android.preference.PreferenceManager;
 import android.preference.PreferenceScreen;
+import android.provider.Settings;
 import android.view.Gravity;
 import android.widget.CompoundButton;
 import android.widget.Switch;
@@ -31,6 +34,10 @@ import android.widget.Switch;
 import com.android.settings.R;
 import com.android.settings.fuelgauge.BatteryStatsHelper;
 
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.List;
+
 /**
  * Location access settings.
  */
@@ -96,7 +103,21 @@ public class LocationSettings extends LocationSettingsBase
         mStatsHelper.destroy();
     }
 
+    private void addPreferencesSorted(List<Preference> prefs, PreferenceGroup container) {
+        // If there's some items to display, sort the items and add them to the container.
+        Collections.sort(prefs, new Comparator<Preference>() {
+            @Override
+            public int compare(Preference lhs, Preference rhs) {
+                return lhs.getTitle().toString().compareTo(rhs.getTitle().toString());
+            }
+        });
+        for (Preference entry : prefs) {
+            container.addPreference(entry);
+        }
+    }
+
     private PreferenceScreen createPreferenceHierarchy() {
+        final PreferenceActivity activity = (PreferenceActivity) getActivity();
         PreferenceScreen root = getPreferenceScreen();
         if (root != null) {
             root.removeAll();
@@ -109,7 +130,6 @@ public class LocationSettings extends LocationSettingsBase
                 new Preference.OnPreferenceClickListener() {
                     @Override
                     public boolean onPreferenceClick(Preference preference) {
-                        PreferenceActivity activity = (PreferenceActivity) getActivity();
                         activity.startPreferencePanel(
                                 LocationMode.class.getName(), null,
                                 R.string.location_mode_screen_title, null, LocationSettings.this,
@@ -117,15 +137,28 @@ public class LocationSettings extends LocationSettingsBase
                         return true;
                     }
                 });
+
+        final PreferenceManager preferenceManager = getPreferenceManager();
+
         mRecentLocationRequests =
                 (PreferenceCategory) root.findPreference(KEY_RECENT_LOCATION_REQUESTS);
-        mLocationServices = (PreferenceCategory) root.findPreference(KEY_LOCATION_SERVICES);
-
-        PreferenceActivity activity = (PreferenceActivity) getActivity();
         RecentLocationApps recentApps = new RecentLocationApps(activity, mStatsHelper);
-        recentApps.fillAppList(mRecentLocationRequests);
+        List<Preference> recentLocationRequests = recentApps.getAppList(preferenceManager);
+        if (recentLocationRequests.size() > 0) {
+            addPreferencesSorted(recentLocationRequests, mRecentLocationRequests);
+        } else {
+            // If there's no item to display, add a "No recent apps" item.
+            PreferenceScreen screen = preferenceManager.createPreferenceScreen(activity);
+            screen.setTitle(R.string.location_no_recent_apps);
+            screen.setSelectable(false);
+            screen.setEnabled(false);
+            mRecentLocationRequests.addPreference(screen);
+        }
 
-        SettingsInjector.addInjectedSettings(mLocationServices, activity, getPreferenceManager());
+        mLocationServices = (PreferenceCategory) root.findPreference(KEY_LOCATION_SERVICES);
+        List<Preference> locationServices = SettingsInjector.getInjectedSettings(
+                activity, preferenceManager);
+        addPreferencesSorted(locationServices, mLocationServices);
 
         // Only show the master switch when we're not in multi-pane mode, and not being used as
         // Setup Wizard.
@@ -155,25 +188,24 @@ public class LocationSettings extends LocationSettingsBase
     @Override
     public void onModeChanged(int mode) {
         switch (mode) {
-            case MODE_LOCATION_OFF:
+            case Settings.Secure.LOCATION_MODE_OFF:
                 mLocationMode.setSummary(R.string.location_mode_location_off_title);
                 break;
-            case MODE_SENSORS_ONLY:
+            case Settings.Secure.LOCATION_MODE_SENSORS_ONLY:
                 mLocationMode.setSummary(R.string.location_mode_sensors_only_title);
                 break;
-            case MODE_BATTERY_SAVING:
+            case Settings.Secure.LOCATION_MODE_BATTERY_SAVING:
                 mLocationMode.setSummary(R.string.location_mode_battery_saving_title);
                 break;
-            case MODE_HIGH_ACCURACY:
+            case Settings.Secure.LOCATION_MODE_HIGH_ACCURACY:
                 mLocationMode.setSummary(R.string.location_mode_high_accuracy_title);
                 break;
             default:
                 break;
         }
 
-        boolean enabled = (mode != MODE_LOCATION_OFF);
+        boolean enabled = (mode != Settings.Secure.LOCATION_MODE_OFF);
         mLocationMode.setEnabled(enabled);
-        mRecentLocationRequests.setEnabled(enabled);
         mLocationServices.setEnabled(enabled);
 
         if (enabled != mSwitch.isChecked()) {
@@ -194,9 +226,9 @@ public class LocationSettings extends LocationSettingsBase
     @Override
     public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
         if (isChecked) {
-            setLocationMode(MODE_HIGH_ACCURACY);
+            setLocationMode(Settings.Secure.LOCATION_MODE_HIGH_ACCURACY);
         } else {
-            setLocationMode(MODE_LOCATION_OFF);
+            setLocationMode(Settings.Secure.LOCATION_MODE_OFF);
         }
     }
 }
index b3c6f70..415e343 100644 (file)
@@ -20,10 +20,8 @@ import android.content.ContentQueryMap;
 import android.content.ContentResolver;
 import android.content.Context;
 import android.database.Cursor;
-import android.location.LocationManager;
 import android.os.UserManager;
 import android.provider.Settings;
-import android.util.Log;
 
 import com.android.settings.SettingsPreferenceFragment;
 
@@ -35,17 +33,6 @@ import java.util.Observer;
  * settings.
  */
 public abstract class LocationSettingsBase extends SettingsPreferenceFragment {
-    private static final String TAG = LocationSettingsBase.class.getSimpleName();
-
-    /** Location disabled */
-    public static final int MODE_LOCATION_OFF = 0;
-    /** GPS-only */
-    public static final int MODE_SENSORS_ONLY = 1;
-    /** Network location only */
-    public static final int MODE_BATTERY_SAVING = 2;
-    /** GPS and network location */
-    public static final int MODE_HIGH_ACCURACY = 3;
-
     private ContentQueryMap mContentQueryMap;
     private Observer mSettingsObserver;
 
@@ -88,51 +75,17 @@ public abstract class LocationSettingsBase extends SettingsPreferenceFragment {
     public abstract void onModeChanged(int mode);
 
     public void setLocationMode(int mode) {
-        boolean gps = false;
-        boolean network = false;
-        switch (mode) {
-            case MODE_LOCATION_OFF:
-                break;
-            case MODE_SENSORS_ONLY:
-                gps = true;
-                break;
-            case MODE_BATTERY_SAVING:
-                network = true;
-                break;
-            case MODE_HIGH_ACCURACY:
-                gps = true;
-                network = true;
-                break;
-            default:
-                Log.wtf(TAG, "Invalid location mode: " + mode);
-        }
         final UserManager um = (UserManager) getActivity().getSystemService(Context.USER_SERVICE);
         if (um.hasUserRestriction(UserManager.DISALLOW_SHARE_LOCATION)) {
             return;
         }
-        // TODO(lifu): use new atomic API to change location mode.
-        Settings.Secure.setLocationProviderEnabled(
-                getContentResolver(), LocationManager.GPS_PROVIDER, gps);
-        Settings.Secure.setLocationProviderEnabled(
-                getContentResolver(), LocationManager.NETWORK_PROVIDER, network);
+        Settings.Secure.setLocationMode(getContentResolver(), mode);
         refreshLocationMode();
     }
 
     public void refreshLocationMode() {
         ContentResolver res = getContentResolver();
-        boolean gpsEnabled = Settings.Secure.isLocationProviderEnabled(
-                res, LocationManager.GPS_PROVIDER);
-        boolean networkEnabled = Settings.Secure.isLocationProviderEnabled(
-                res, LocationManager.NETWORK_PROVIDER);
-        boolean enabled = gpsEnabled || networkEnabled;
-        if (!enabled) {
-            onModeChanged(MODE_LOCATION_OFF);
-        } else if (gpsEnabled && !networkEnabled) {
-            onModeChanged(MODE_SENSORS_ONLY);
-        } else if (!gpsEnabled && networkEnabled) {
-            onModeChanged(MODE_BATTERY_SAVING);
-        } else {
-            onModeChanged(MODE_HIGH_ACCURACY);
-        }
+        int mode = Settings.Secure.getLocationMode(getContentResolver());
+        onModeChanged(mode);
     }
 }
index 9a59563..cbf8351 100644 (file)
@@ -24,7 +24,6 @@ import android.graphics.drawable.Drawable;
 import android.os.Bundle;
 import android.preference.Preference;
 import android.preference.PreferenceActivity;
-import android.preference.PreferenceCategory;
 import android.preference.PreferenceManager;
 import android.preference.PreferenceScreen;
 import android.util.Log;
@@ -35,8 +34,6 @@ import com.android.settings.fuelgauge.BatterySipper;
 import com.android.settings.fuelgauge.BatteryStatsHelper;
 
 import java.util.ArrayList;
-import java.util.Collections;
-import java.util.Comparator;
 import java.util.HashMap;
 import java.util.List;
 
@@ -143,7 +140,7 @@ public class RecentLocationApps {
      * Fills a list of applications which queried location recently within
      * specified time.
      */
-    public void fillAppList(PreferenceCategory container) {
+    public List<Preference> getAppList(PreferenceManager preferenceManager) {
         // Retrieve Uid-based battery blaming info and generate a package to BatterySipper HashMap
         // for later faster looking up.
         mStatsHelper.refreshStats();
@@ -166,10 +163,9 @@ public class RecentLocationApps {
                     AppOpsManager.OP_MONITOR_LOCATION,
                     AppOpsManager.OP_MONITOR_HIGH_POWER_LOCATION,
                 });
-        PreferenceManager preferenceManager = container.getPreferenceManager();
 
         // Process the AppOps list and generate a preference list.
-        ArrayList<PreferenceScreen> prefs = new ArrayList<PreferenceScreen>();
+        ArrayList<Preference> prefs = new ArrayList<Preference>();
         long now = System.currentTimeMillis();
         for (AppOpsManager.PackageOps ops : appOps) {
             BatterySipperWrapper wrapper = sipperMap.get(ops.getUid());
@@ -179,25 +175,7 @@ public class RecentLocationApps {
             }
         }
 
-        if (prefs.size() > 0) {
-            // If there's some items to display, sort the items and add them to the container.
-            Collections.sort(prefs, new Comparator<PreferenceScreen>() {
-                @Override
-                public int compare(PreferenceScreen lhs, PreferenceScreen rhs) {
-                    return lhs.getTitle().toString().compareTo(rhs.getTitle().toString());
-                }
-            });
-            for (PreferenceScreen entry : prefs) {
-                container.addPreference(entry);
-            }
-        } else {
-            // If there's no item to display, add a "No recent apps" item.
-            PreferenceScreen screen = preferenceManager.createPreferenceScreen(mActivity);
-            screen.setTitle(R.string.location_no_recent_apps);
-            screen.setSelectable(false);
-            screen.setEnabled(false);
-            container.addPreference(screen);
-        }
+        return prefs;
     }
 
     /**
index 258f3fd..0b7c172 100644 (file)
@@ -16,7 +16,6 @@
 
 package com.android.settings.location;
 
-import android.R;
 import android.content.Context;
 import android.content.Intent;
 import android.content.pm.PackageManager;
@@ -32,7 +31,6 @@ import android.os.Handler;
 import android.os.Message;
 import android.os.Messenger;
 import android.preference.Preference;
-import android.preference.PreferenceGroup;
 import android.preference.PreferenceManager;
 import android.preference.PreferenceScreen;
 import android.text.TextUtils;
@@ -42,6 +40,8 @@ import android.util.Xml;
 import org.xmlpull.v1.XmlPullParser;
 import org.xmlpull.v1.XmlPullParserException;
 
+import com.android.settings.R;
+
 import java.io.IOException;
 import java.util.ArrayList;
 import java.util.List;
@@ -56,11 +56,15 @@ import java.util.List;
  * Code-sharing would require extracting {@link
  * android.content.pm.RegisteredServicesCache#parseServiceAttributes(android.content.res.Resources,
  * String, android.util.AttributeSet)} into an interface, which didn't seem worth it.
+ *
+ * TODO: register a broadcast receiver that calls updateUI() when it receives
+ * {@link SettingInjectorService#UPDATE_INTENT}.
  */
 class SettingsInjector {
-
     private static final String TAG = "SettingsInjector";
 
+    private static final long INJECTED_STATUS_UPDATE_TIMEOUT_MILLIS = 1000;
+
     /**
      * Intent action marking the receiver as injecting a setting
      */
@@ -78,22 +82,11 @@ class SettingsInjector {
     public static final String ATTRIBUTES_NAME = "injected-location-setting";
 
     /**
-     * Intent action a client should broadcast when the value of one of its injected settings has
-     * changed, so that the setting can be updated in the UI.
-     *
-     * TODO: register a broadcast receiver that calls updateUI() when it receives this intent
-     */
-    public static final String UPDATE_INTENT =
-            "com.android.settings.InjectedLocationSettingChanged";
-
-    /**
      * Returns a list with one {@link InjectedSetting} object for each {@link android.app.Service}
      * that responds to {@link #RECEIVER_INTENT} and provides the expected setting metadata.
      *
      * Duplicates some code from {@link android.content.pm.RegisteredServicesCache}.
      *
-     * TODO: sort alphabetically
-     *
      * TODO: unit test
      */
     public static List<InjectedSetting> getSettings(Context context) {
@@ -173,15 +166,17 @@ class SettingsInjector {
     private static InjectedSetting parseAttributes(
             String packageName, String className, Resources res, AttributeSet attrs) {
 
-        TypedArray sa = res.obtainAttributes(attrs, R.styleable.InjectedLocationSetting);
+        TypedArray sa = res.obtainAttributes(attrs, android.R.styleable.InjectedLocationSetting);
         try {
             // Note that to help guard against malicious string injection, we do not allow dynamic
             // specification of the label (setting title)
-            final int labelId = sa.getResourceId(R.styleable.InjectedLocationSetting_label, 0);
-            final String label = sa.getString(R.styleable.InjectedLocationSetting_label);
-            final int iconId = sa.getResourceId(R.styleable.InjectedLocationSetting_icon, 0);
+            final int labelId = sa.getResourceId(
+                    android.R.styleable.InjectedLocationSetting_label, 0);
+            final String label = sa.getString(android.R.styleable.InjectedLocationSetting_label);
+            final int iconId = sa.getResourceId(
+                    android.R.styleable.InjectedLocationSetting_icon, 0);
             final String settingsActivity =
-                    sa.getString(R.styleable.InjectedLocationSetting_settingsActivity);
+                    sa.getString(android.R.styleable.InjectedLocationSetting_settingsActivity);
             if (Log.isLoggable(TAG, Log.DEBUG)) {
                 Log.d(TAG, "parsed labelId: " + labelId + ", label: " + label
                         + ", iconId: " + iconId);
@@ -196,35 +191,84 @@ class SettingsInjector {
         }
     }
 
+    private static final class StatusLoader {
+        private final Context mContext;
+        private final Intent mIntent;
+        private final StatusLoader mPrev;
+
+        private boolean mLoaded = false;
+
+        /**
+         * Creates a loader and chains with the previous loader.
+         */
+        public StatusLoader(Context context, Intent intent, StatusLoader prev) {
+            mContext = context;
+            mIntent = intent;
+            mPrev = prev;
+        }
+
+        /**
+         * If the current message hasn't been loaded, loads the status messages
+         * and set time out for the next message.
+         */
+        public void loadIfNotLoaded() {
+            if (mLoaded) {
+                return;
+            }
+
+            mContext.startService(mIntent);
+            if (mPrev != null) {
+                Handler handler = new Handler() {
+                    @Override
+                    public void handleMessage(Message msg) {
+                        // Continue with the next item in the chain.
+                        mPrev.loadIfNotLoaded();
+                    }
+                };
+                // Ensure that we start loading the previous setting in the chain if the current
+                // setting hasn't loaded before the timeout
+                handler.sendMessageDelayed(
+                        Message.obtain(handler), INJECTED_STATUS_UPDATE_TIMEOUT_MILLIS);
+            }
+            mLoaded = true;
+        }
+    }
+
     /**
-     * Add settings that other apps have injected.
+     * Gets a list of preferences that other apps have injected.
      *
      * TODO: extract InjectedLocationSettingGetter that returns an iterable over
      * InjectedSetting objects, so that this class can focus on UI
      */
-    public static void addInjectedSettings(PreferenceGroup group, Context context,
+    public static List<Preference> getInjectedSettings(Context context,
             PreferenceManager preferenceManager) {
 
         Iterable<InjectedSetting> settings = getSettings(context);
+        ArrayList<Preference> prefs = new ArrayList<Preference>();
+        StatusLoader loader = null;
         for (InjectedSetting setting : settings) {
-            Preference pref = addServiceSetting(context, group, setting, preferenceManager);
+            Preference pref = addServiceSetting(context, prefs, setting, preferenceManager);
+            Intent intent = createUpdatingIntent(context, pref, setting, loader);
+            loader = new StatusLoader(context, intent, loader);
+        }
 
-            // TODO: to prevent churn from multiple live broadcast receivers, don't trigger
-            // the next update until the sooner of: the current update completes or 1-2 seconds
-            // after the current update was started.
-            updateSetting(context, pref, setting);
+        // Start a thread to load each list item status.
+        if (loader != null) {
+            loader.loadIfNotLoaded();
         }
+
+        return prefs;
     }
 
     /**
      * Adds an injected setting to the root with status "Loading...".
      */
     private static PreferenceScreen addServiceSetting(Context context,
-            PreferenceGroup group, InjectedSetting info, PreferenceManager preferenceManager) {
+            List<Preference> prefs, InjectedSetting info, PreferenceManager preferenceManager) {
 
         PreferenceScreen screen = preferenceManager.createPreferenceScreen(context);
         screen.setTitle(info.title);
-        screen.setSummary("Loading...");
+        screen.setSummary(R.string.location_loading_injected_setting);
         PackageManager pm = context.getPackageManager();
         Drawable icon = pm.getDrawable(info.packageName, info.iconId, null);
         screen.setIcon(icon);
@@ -233,15 +277,17 @@ class SettingsInjector {
         settingIntent.setClassName(info.packageName, info.settingsActivity);
         screen.setIntent(settingIntent);
 
-        group.addPreference(screen);
+        prefs.add(screen);
         return screen;
     }
 
     /**
-     * Ask the receiver for the current status for the setting, and display it when it replies.
+     * Creates an Intent to ask the receiver for the current status for the setting, and display it
+     * when it replies.
      */
-    private static void updateSetting(Context context,
-            final Preference pref, final InjectedSetting info) {
+    private static Intent createUpdatingIntent(Context context,
+            final Preference pref, final InjectedSetting info, final StatusLoader prev) {
+        final Intent receiverIntent = info.getServiceIntent();
         Handler handler = new Handler() {
             @Override
             public void handleMessage(Message msg) {
@@ -253,14 +299,16 @@ class SettingsInjector {
                 }
                 pref.setSummary(status);
                 pref.setEnabled(enabled);
+                if (prev != null) {
+                    prev.loadIfNotLoaded();
+                }
             }
         };
         Messenger messenger = new Messenger(handler);
-        Intent receiverIntent = info.getServiceIntent();
         receiverIntent.putExtra(SettingInjectorService.MESSENGER_KEY, messenger);
         if (Log.isLoggable(TAG, Log.DEBUG)) {
             Log.d(TAG, info + ": sending rcv-intent: " + receiverIntent + ", handler: " + handler);
         }
-        context.startService(receiverIntent);
+        return receiverIntent;
     }
 }
index 7beb17c..71994a9 100644 (file)
@@ -521,8 +521,14 @@ public class SettingsAppWidgetProvider extends AppWidgetProvider {
         @Override
         public int getActualState(Context context) {
             ContentResolver resolver = context.getContentResolver();
-            return Settings.Secure.isLocationMasterSwitchEnabled(resolver)
-                    ? STATE_ENABLED : STATE_DISABLED;
+            int currentLocationMode = Settings.Secure.getLocationMode(resolver);
+            switch (currentLocationMode) {
+                case Settings.Secure.LOCATION_MODE_BATTERY_SAVING:
+                case Settings.Secure.LOCATION_MODE_OFF:
+                    return STATE_DISABLED;
+            }
+
+            return STATE_ENABLED;
         }
 
         @Override
@@ -541,11 +547,14 @@ public class SettingsAppWidgetProvider extends AppWidgetProvider {
                     final UserManager um =
                             (UserManager) context.getSystemService(Context.USER_SERVICE);
                     if (!um.hasUserRestriction(UserManager.DISALLOW_SHARE_LOCATION)) {
-                        Settings.Secure.setLocationMasterSwitchEnabled(resolver, desiredState);
+                        int mode = desiredState
+                                ? Settings.Secure.LOCATION_MODE_HIGH_ACCURACY
+                                : Settings.Secure.LOCATION_MODE_BATTERY_SAVING;
+                        Settings.Secure.setLocationMode(resolver, mode);
                         return desiredState;
                     }
 
-                    return Settings.Secure.isLocationMasterSwitchEnabled(resolver);
+                    return getActualState(context) == STATE_ENABLED;
                 }
 
                 @Override