summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Android.mk1
-rw-r--r--core/java/com/android/internal/car/ICarServiceHelper.aidl24
-rw-r--r--libs/hwui/Android.bp15
-rw-r--r--packages/SettingsLib/res/layout/preference_category_material_settings.xml66
-rw-r--r--packages/SettingsLib/res/layout/usage_bottom_label.xml20
-rw-r--r--packages/SettingsLib/res/layout/usage_side_label.xml20
-rw-r--r--packages/SettingsLib/res/layout/usage_view.xml99
-rw-r--r--packages/SettingsLib/res/values/attrs.xml8
-rw-r--r--packages/SettingsLib/src/com/android/settingslib/graph/BottomLabelLayout.java97
-rw-r--r--packages/SettingsLib/src/com/android/settingslib/graph/UsageGraph.java277
-rw-r--r--packages/SettingsLib/src/com/android/settingslib/graph/UsageView.java141
-rw-r--r--packages/SettingsLib/src/com/android/settingslib/wifi/AccessPoint.java41
-rw-r--r--packages/SettingsLib/src/com/android/settingslib/wifi/AccessPointPreference.java5
-rw-r--r--packages/SettingsLib/tests/integ/src/com/android/settingslib/wifi/AccessPointTest.java101
-rw-r--r--packages/SettingsLib/tests/robotests/src/com/android/settingslib/graph/BottomLabelLayoutTest.java70
-rw-r--r--packages/SystemUI/colorextraction/src/com/google/android/colorextraction/ColorExtractor.java157
-rw-r--r--packages/SystemUI/colorextraction/src/com/google/android/colorextraction/types/ExtractionType.java15
-rw-r--r--packages/SystemUI/colorextraction/src/com/google/android/colorextraction/types/Tonal.java124
-rw-r--r--packages/SystemUI/colorextraction/tests/src/com/google/android/colorextraction/ColorExtractorTest.java114
-rw-r--r--packages/SystemUI/colorextraction/tests/src/com/google/android/colorextraction/types/TonalTest.java4
-rw-r--r--packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialog.java6
-rw-r--r--packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java7
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/SignalClusterView.java4
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java36
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java4
-rw-r--r--packages/SystemUI/src/com/android/systemui/volume/VolumeDialogImpl.java6
-rw-r--r--services/core/java/com/android/server/car/CarServiceHelperService.java91
-rw-r--r--services/java/com/android/server/SystemServer.java7
-rw-r--r--services/usb/java/com/android/server/usb/UsbDeviceManager.java9
-rw-r--r--telephony/java/android/telephony/CarrierConfigManager.java21
30 files changed, 727 insertions, 863 deletions
diff --git a/Android.mk b/Android.mk
index d847d49e89c4..6631adace544 100644
--- a/Android.mk
+++ b/Android.mk
@@ -385,6 +385,7 @@ LOCAL_SRC_FILES += \
core/java/com/android/internal/appwidget/IAppWidgetHost.aidl \
core/java/com/android/internal/backup/IBackupTransport.aidl \
core/java/com/android/internal/backup/IObbBackupService.aidl \
+ core/java/com/android/internal/car/ICarServiceHelper.aidl \
core/java/com/android/internal/inputmethod/IInputContentUriToken.aidl \
core/java/com/android/internal/policy/IKeyguardDrawnCallback.aidl \
core/java/com/android/internal/policy/IKeyguardDismissCallback.aidl \
diff --git a/core/java/com/android/internal/car/ICarServiceHelper.aidl b/core/java/com/android/internal/car/ICarServiceHelper.aidl
new file mode 100644
index 000000000000..9ee330be060b
--- /dev/null
+++ b/core/java/com/android/internal/car/ICarServiceHelper.aidl
@@ -0,0 +1,24 @@
+/*
+ * Copyright (C) 2017 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.internal.car;
+
+/**
+ * Helper API for car service. Only for itneraction between system server and car service.
+ * @hide
+ */
+interface ICarServiceHelper {
+}
diff --git a/libs/hwui/Android.bp b/libs/hwui/Android.bp
index 07ff27de794f..4cfb9d88c716 100644
--- a/libs/hwui/Android.bp
+++ b/libs/hwui/Android.bp
@@ -5,11 +5,6 @@ cc_defaults {
//"hwui_bugreport_font_cache_usage",
//"hwui_compile_for_perf",
-
- // Enables fine-grained GLES error checking
- // If enabled, every GLES call is wrapped & error checked
- // Has moderate overhead
- //"hwui_enable_opengl-validation",
],
cflags: [
@@ -108,7 +103,6 @@ cc_defaults {
name: "hwui_enable_opengl_validation",
defaults: ["hwui_debug"],
cflags: ["-DDEBUG_OPENGL=3"],
- srcs: ["debug/wrap_gles.cpp"],
include_dirs: ["frameworks/native/opengl/libs/GLES2"],
}
@@ -242,7 +236,14 @@ cc_defaults {
cc_library {
name: "libhwui",
- defaults: ["libhwui_defaults"],
+ defaults: [
+ "libhwui_defaults",
+
+ // Enables fine-grained GLES error checking
+ // If enabled, every GLES call is wrapped & error checked
+ // Has moderate overhead
+ "hwui_enable_opengl_validation",
+],
}
// ------------------------
diff --git a/packages/SettingsLib/res/layout/preference_category_material_settings.xml b/packages/SettingsLib/res/layout/preference_category_material_settings.xml
new file mode 100644
index 000000000000..741435ec9b43
--- /dev/null
+++ b/packages/SettingsLib/res/layout/preference_category_material_settings.xml
@@ -0,0 +1,66 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2017 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.
+ -->
+
+<!-- Based off frameworks/base/core/res/res/layout/preference_category_material.xml
+ except that this supports icon -->
+<FrameLayout
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_marginTop="8dp"
+ android:layout_marginBottom="8dp"
+ android:paddingStart="?android:attr/listPreferredItemPaddingStart" >
+
+ <LinearLayout
+ android:id="@+id/icon_container"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:gravity="start|center_vertical"
+ android:orientation="horizontal">
+ <com.android.internal.widget.PreferenceImageView
+ android:id="@android:id/icon"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:tint="?android:attr/textColorPrimary"
+ android:maxWidth="18dp"
+ android:maxHeight="18dp"/>
+ </LinearLayout>
+
+ <LinearLayout
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:paddingStart="56dp"
+ android:orientation="vertical">
+ <TextView
+ android:id="@android:id/title"
+ android:layout_marginTop="16dp"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:textAppearance="@android:style/TextAppearance.Material.Body2"
+ android:textColor="?android:attr/colorAccent"
+ android:paddingEnd="?android:attr/listPreferredItemPaddingEnd"/>
+ <TextView
+ android:id="@android:id/summary"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:textAppearance="?android:attr/textAppearanceListItemSecondary"
+ android:textColor="?android:attr/textColorSecondary"
+ android:ellipsize="end"
+ android:singleLine="true" />
+ </LinearLayout>
+
+</FrameLayout> \ No newline at end of file
diff --git a/packages/SettingsLib/res/layout/usage_bottom_label.xml b/packages/SettingsLib/res/layout/usage_bottom_label.xml
deleted file mode 100644
index 6c168806338e..000000000000
--- a/packages/SettingsLib/res/layout/usage_bottom_label.xml
+++ /dev/null
@@ -1,20 +0,0 @@
-<!--
- Copyright (C) 2016 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.
--->
-<TextView
- xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:textAppearance="?android:attr/textAppearanceSmall" />
diff --git a/packages/SettingsLib/res/layout/usage_side_label.xml b/packages/SettingsLib/res/layout/usage_side_label.xml
deleted file mode 100644
index 6c168806338e..000000000000
--- a/packages/SettingsLib/res/layout/usage_side_label.xml
+++ /dev/null
@@ -1,20 +0,0 @@
-<!--
- Copyright (C) 2016 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.
--->
-<TextView
- xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:textAppearance="?android:attr/textAppearanceSmall" />
diff --git a/packages/SettingsLib/res/layout/usage_view.xml b/packages/SettingsLib/res/layout/usage_view.xml
deleted file mode 100644
index da66814f49cb..000000000000
--- a/packages/SettingsLib/res/layout/usage_view.xml
+++ /dev/null
@@ -1,99 +0,0 @@
-<!--
- Copyright (C) 2016 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.
--->
-<LinearLayout
- xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:orientation="vertical">
-
- <LinearLayout
- android:id="@+id/graph_label_group"
- android:layout_width="match_parent"
- android:layout_height="0dp"
- android:layout_weight="1"
- android:orientation="horizontal"
- android:clipChildren="false"
- android:clipToPadding="false">
-
- <LinearLayout
- android:id="@+id/label_group"
- android:layout_width="@dimen/usage_graph_labels_width"
- android:layout_height="match_parent"
- android:orientation="vertical">
-
- <include android:id="@+id/label_top"
- layout="@layout/usage_side_label" />
-
- <Space
- android:id="@+id/space1"
- android:layout_width="wrap_content"
- android:layout_height="0dp"
- android:layout_weight="1" />
-
- <include android:id="@+id/label_middle"
- layout="@layout/usage_side_label" />
-
- <Space
- android:id="@+id/space2"
- android:layout_width="wrap_content"
- android:layout_height="0dp"
- android:layout_weight="1" />
-
- <include android:id="@+id/label_bottom"
- layout="@layout/usage_side_label" />
-
- </LinearLayout>
-
- <com.android.settingslib.graph.UsageGraph
- android:id="@+id/usage_graph"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:layout_weight="1"
- android:layout_marginTop="@dimen/usage_graph_margin_top_bottom"
- android:layout_marginBottom="@dimen/usage_graph_margin_top_bottom" />
-
- </LinearLayout>
-
- <LinearLayout
- android:id="@+id/bottom_label_group"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:orientation="horizontal">
- <Space
- android:id="@+id/bottom_label_space"
- android:layout_width="@dimen/usage_graph_labels_width"
- android:layout_height="wrap_content"/>
- <com.android.settingslib.graph.BottomLabelLayout
- android:layout_width="0dp"
- android:layout_height="wrap_content"
- android:layout_weight="1"
- android:orientation="horizontal"
- android:layoutDirection="ltr">
- <include android:id="@+id/label_start"
- layout="@layout/usage_side_label" />
-
- <Space
- android:id="@+id/spacer"
- android:layout_width="40dp"
- android:layout_height="wrap_content"
- android:layout_weight="1" />
-
- <include android:id="@+id/label_end"
- layout="@layout/usage_side_label" />
- </com.android.settingslib.graph.BottomLabelLayout>
- </LinearLayout>
-
-</LinearLayout>
diff --git a/packages/SettingsLib/res/values/attrs.xml b/packages/SettingsLib/res/values/attrs.xml
index c931722b0963..a8a179358744 100644
--- a/packages/SettingsLib/res/values/attrs.xml
+++ b/packages/SettingsLib/res/values/attrs.xml
@@ -46,14 +46,6 @@
<attr name="wifi_signal" format="reference" />
<attr name="wifi_friction" format="reference" />
- <declare-styleable name="UsageView">
- <attr name="android:colorAccent" />
- <attr name="sideLabels" format="reference" />
- <attr name="bottomLabels" format="reference" />
- <attr name="textColor" format="color" />
- <attr name="android:gravity" />
- </declare-styleable>
-
<attr name="footerPreferenceStyle" format="reference" />
</resources>
diff --git a/packages/SettingsLib/src/com/android/settingslib/graph/BottomLabelLayout.java b/packages/SettingsLib/src/com/android/settingslib/graph/BottomLabelLayout.java
deleted file mode 100644
index 8161dd4bb934..000000000000
--- a/packages/SettingsLib/src/com/android/settingslib/graph/BottomLabelLayout.java
+++ /dev/null
@@ -1,97 +0,0 @@
-/*
- * Copyright (C) 2017 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.settingslib.graph;
-
-import android.annotation.Nullable;
-import android.content.Context;
-import android.support.annotation.VisibleForTesting;
-import android.util.AttributeSet;
-import android.view.Gravity;
-import android.view.View;
-import android.widget.LinearLayout;
-
-import com.android.settingslib.R;
-
-/**
- * An extension of LinearLayout that automatically switches to vertical
- * orientation when it can't fit its child views horizontally.
- *
- * Main logic in this class comes from {@link android.support.v7.widget.ButtonBarLayout}.
- * Compared with {@link android.support.v7.widget.ButtonBarLayout}, this layout won't reverse
- * children's order and won't update the minimum height
- */
-public class BottomLabelLayout extends LinearLayout {
- private static final String TAG = "BottomLabelLayout";
-
- public BottomLabelLayout(Context context,
- @Nullable AttributeSet attrs) {
- super(context, attrs);
- }
-
- @Override
- protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
- final int widthSize = MeasureSpec.getSize(widthMeasureSpec);
- final boolean isStacked = isStacked();
- boolean needsRemeasure = false;
-
- // If we're not stacked, make sure the measure spec is AT_MOST rather
- // than EXACTLY. This ensures that we'll still get TOO_SMALL so that we
- // know to stack the buttons.
- final int initialWidthMeasureSpec;
- if (!isStacked && MeasureSpec.getMode(widthMeasureSpec) == MeasureSpec.EXACTLY) {
- initialWidthMeasureSpec = MeasureSpec.makeMeasureSpec(widthSize, MeasureSpec.AT_MOST);
-
- // We'll need to remeasure again to fill excess space.
- needsRemeasure = true;
- } else {
- initialWidthMeasureSpec = widthMeasureSpec;
- }
-
- super.onMeasure(initialWidthMeasureSpec, heightMeasureSpec);
- if (!isStacked) {
- final int measuredWidth = getMeasuredWidthAndState();
- final int measuredWidthState = measuredWidth & View.MEASURED_STATE_MASK;
-
- if (measuredWidthState == View.MEASURED_STATE_TOO_SMALL) {
- setStacked(true);
- // Measure again in the new orientation.
- needsRemeasure = true;
- }
- }
-
- if (needsRemeasure) {
- super.onMeasure(widthMeasureSpec, heightMeasureSpec);
- }
-
- }
-
- @VisibleForTesting
- void setStacked(boolean stacked) {
- setOrientation(stacked ? LinearLayout.VERTICAL : LinearLayout.HORIZONTAL);
- setGravity(stacked ? Gravity.START : Gravity.BOTTOM);
-
- final View spacer = findViewById(R.id.spacer);
- if (spacer != null) {
- spacer.setVisibility(stacked ? View.GONE : View.VISIBLE);
- }
- }
-
- private boolean isStacked() {
- return getOrientation() == LinearLayout.VERTICAL;
- }
-}
diff --git a/packages/SettingsLib/src/com/android/settingslib/graph/UsageGraph.java b/packages/SettingsLib/src/com/android/settingslib/graph/UsageGraph.java
deleted file mode 100644
index 1fff0fbb3f61..000000000000
--- a/packages/SettingsLib/src/com/android/settingslib/graph/UsageGraph.java
+++ /dev/null
@@ -1,277 +0,0 @@
-/*
- * Copyright (C) 2016 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.settingslib.graph;
-
-import android.annotation.Nullable;
-import android.content.Context;
-import android.content.res.Resources;
-import android.graphics.Canvas;
-import android.graphics.CornerPathEffect;
-import android.graphics.DashPathEffect;
-import android.graphics.LinearGradient;
-import android.graphics.Paint;
-import android.graphics.Paint.Cap;
-import android.graphics.Paint.Join;
-import android.graphics.Paint.Style;
-import android.graphics.Path;
-import android.graphics.Shader.TileMode;
-import android.graphics.drawable.Drawable;
-import android.util.AttributeSet;
-import android.util.SparseIntArray;
-import android.util.TypedValue;
-import android.view.View;
-import com.android.settingslib.R;
-
-public class UsageGraph extends View {
-
- private static final int PATH_DELIM = -1;
-
- private final Paint mLinePaint;
- private final Paint mFillPaint;
- private final Paint mDottedPaint;
-
- private final Drawable mDivider;
- private final Drawable mTintedDivider;
- private final int mDividerSize;
-
- private final Path mPath = new Path();
-
- // Paths in coordinates they are passed in.
- private final SparseIntArray mPaths = new SparseIntArray();
- // Paths in local coordinates for drawing.
- private final SparseIntArray mLocalPaths = new SparseIntArray();
- private final int mCornerRadius;
-
- private int mAccentColor;
- private boolean mShowProjection;
- private boolean mProjectUp;
-
- private float mMaxX = 100;
- private float mMaxY = 100;
-
- private float mMiddleDividerLoc = .5f;
- private int mMiddleDividerTint = -1;
- private int mTopDividerTint = -1;
-
- public UsageGraph(Context context, @Nullable AttributeSet attrs) {
- super(context, attrs);
- final Resources resources = context.getResources();
-
- mLinePaint = new Paint();
- mLinePaint.setStyle(Style.STROKE);
- mLinePaint.setStrokeCap(Cap.ROUND);
- mLinePaint.setStrokeJoin(Join.ROUND);
- mLinePaint.setAntiAlias(true);
- mCornerRadius = resources.getDimensionPixelSize(R.dimen.usage_graph_line_corner_radius);
- mLinePaint.setPathEffect(new CornerPathEffect(mCornerRadius));
- mLinePaint.setStrokeWidth(resources.getDimensionPixelSize(R.dimen.usage_graph_line_width));
-
- mFillPaint = new Paint(mLinePaint);
- mFillPaint.setStyle(Style.FILL);
-
- mDottedPaint = new Paint(mLinePaint);
- mDottedPaint.setStyle(Style.STROKE);
- float dots = resources.getDimensionPixelSize(R.dimen.usage_graph_dot_size);
- float interval = resources.getDimensionPixelSize(R.dimen.usage_graph_dot_interval);
- mDottedPaint.setStrokeWidth(dots * 3);
- mDottedPaint.setPathEffect(new DashPathEffect(new float[] {dots, interval}, 0));
- mDottedPaint.setColor(context.getColor(R.color.usage_graph_dots));
-
- TypedValue v = new TypedValue();
- context.getTheme().resolveAttribute(com.android.internal.R.attr.listDivider, v, true);
- mDivider = context.getDrawable(v.resourceId);
- mTintedDivider = context.getDrawable(v.resourceId);
- mDividerSize = resources.getDimensionPixelSize(R.dimen.usage_graph_divider_size);
- }
-
- void clearPaths() {
- mPaths.clear();
- }
-
- void setMax(int maxX, int maxY) {
- mMaxX = maxX;
- mMaxY = maxY;
- }
-
- void setDividerLoc(int height) {
- mMiddleDividerLoc = 1 - height / mMaxY;
- }
-
- void setDividerColors(int middleColor, int topColor) {
- mMiddleDividerTint = middleColor;
- mTopDividerTint = topColor;
- }
-
- public void addPath(SparseIntArray points) {
- for (int i = 0; i < points.size(); i++) {
- mPaths.put(points.keyAt(i), points.valueAt(i));
- }
- mPaths.put(points.keyAt(points.size() - 1) + 1, PATH_DELIM);
- calculateLocalPaths();
- postInvalidate();
- }
-
- void setAccentColor(int color) {
- mAccentColor = color;
- mLinePaint.setColor(mAccentColor);
- updateGradient();
- postInvalidate();
- }
-
- void setShowProjection(boolean showProjection, boolean projectUp) {
- mShowProjection = showProjection;
- mProjectUp = projectUp;
- postInvalidate();
- }
-
- @Override
- protected void onSizeChanged(int w, int h, int oldw, int oldh) {
- super.onSizeChanged(w, h, oldw, oldh);
- updateGradient();
- calculateLocalPaths();
- }
-
- private void calculateLocalPaths() {
- if (getWidth() == 0) return;
- mLocalPaths.clear();
- int pendingXLoc = 0;
- int pendingYLoc = PATH_DELIM;
- for (int i = 0; i < mPaths.size(); i++) {
- int x = mPaths.keyAt(i);
- int y = mPaths.valueAt(i);
- if (y == PATH_DELIM) {
- if (i == mPaths.size() - 1 && pendingYLoc != PATH_DELIM) {
- // Connect to the end of the graph.
- mLocalPaths.put(pendingXLoc, pendingYLoc);
- }
- // Clear out any pending points.
- pendingYLoc = PATH_DELIM;
- mLocalPaths.put(pendingXLoc + 1, PATH_DELIM);
- } else {
- final int lx = getX(x);
- final int ly = getY(y);
- pendingXLoc = lx;
- if (mLocalPaths.size() > 0) {
- int lastX = mLocalPaths.keyAt(mLocalPaths.size() - 1);
- int lastY = mLocalPaths.valueAt(mLocalPaths.size() - 1);
- if (lastY != PATH_DELIM && !hasDiff(lastX, lx) && !hasDiff(lastY, ly)) {
- pendingYLoc = ly;
- continue;
- }
- }
- mLocalPaths.put(lx, ly);
- }
- }
- }
-
- private boolean hasDiff(int x1, int x2) {
- return Math.abs(x2 - x1) >= mCornerRadius;
- }
-
- private int getX(float x) {
- return (int) (x / mMaxX * getWidth());
- }
-
- private int getY(float y) {
- return (int) (getHeight() * (1 - (y / mMaxY)));
- }
-
- private void updateGradient() {
- mFillPaint.setShader(new LinearGradient(0, 0, 0, getHeight(),
- getColor(mAccentColor, .2f), 0, TileMode.CLAMP));
- }
-
- private int getColor(int color, float alphaScale) {
- return (color & (((int) (0xff * alphaScale) << 24) | 0xffffff));
- }
-
- @Override
- protected void onDraw(Canvas canvas) {
- // Draw lines across the top, middle, and bottom.
- if (mMiddleDividerLoc != 0) {
- drawDivider(0, canvas, mTopDividerTint);
- }
- drawDivider((int) ((canvas.getHeight() - mDividerSize) * mMiddleDividerLoc), canvas,
- mMiddleDividerTint);
- drawDivider(canvas.getHeight() - mDividerSize, canvas, -1);
-
- if (mLocalPaths.size() == 0) {
- return;
- }
- if (mShowProjection) {
- drawProjection(canvas);
- }
- drawFilledPath(canvas);
- drawLinePath(canvas);
- }
-
- private void drawProjection(Canvas canvas) {
- mPath.reset();
- int x = mLocalPaths.keyAt(mLocalPaths.size() - 2);
- int y = mLocalPaths.valueAt(mLocalPaths.size() - 2);
- mPath.moveTo(x, y);
- mPath.lineTo(canvas.getWidth(), mProjectUp ? 0 : canvas.getHeight());
- canvas.drawPath(mPath, mDottedPaint);
- }
-
- private void drawLinePath(Canvas canvas) {
- mPath.reset();
- mPath.moveTo(mLocalPaths.keyAt(0), mLocalPaths.valueAt(0));
- for (int i = 1; i < mLocalPaths.size(); i++) {
- int x = mLocalPaths.keyAt(i);
- int y = mLocalPaths.valueAt(i);
- if (y == PATH_DELIM) {
- if (++i < mLocalPaths.size()) {
- mPath.moveTo(mLocalPaths.keyAt(i), mLocalPaths.valueAt(i));
- }
- } else {
- mPath.lineTo(x, y);
- }
- }
- canvas.drawPath(mPath, mLinePaint);
- }
-
- private void drawFilledPath(Canvas canvas) {
- mPath.reset();
- float lastStartX = mLocalPaths.keyAt(0);
- mPath.moveTo(mLocalPaths.keyAt(0), mLocalPaths.valueAt(0));
- for (int i = 1; i < mLocalPaths.size(); i++) {
- int x = mLocalPaths.keyAt(i);
- int y = mLocalPaths.valueAt(i);
- if (y == PATH_DELIM) {
- mPath.lineTo(mLocalPaths.keyAt(i - 1), getHeight());
- mPath.lineTo(lastStartX, getHeight());
- mPath.close();
- if (++i < mLocalPaths.size()) {
- lastStartX = mLocalPaths.keyAt(i);
- mPath.moveTo(mLocalPaths.keyAt(i), mLocalPaths.valueAt(i));
- }
- } else {
- mPath.lineTo(x, y);
- }
- }
- canvas.drawPath(mPath, mFillPaint);
- }
-
- private void drawDivider(int y, Canvas canvas, int tintColor) {
- Drawable d = mDivider;
- if (tintColor != -1) {
- mTintedDivider.setTint(tintColor);
- d = mTintedDivider;
- }
- d.setBounds(0, y, canvas.getWidth(), y + mDividerSize);
- d.draw(canvas);
- }
-}
diff --git a/packages/SettingsLib/src/com/android/settingslib/graph/UsageView.java b/packages/SettingsLib/src/com/android/settingslib/graph/UsageView.java
deleted file mode 100644
index e2c05a193882..000000000000
--- a/packages/SettingsLib/src/com/android/settingslib/graph/UsageView.java
+++ /dev/null
@@ -1,141 +0,0 @@
-/*
- * Copyright (C) 2016 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.settingslib.graph;
-
-import android.content.Context;
-import android.content.res.TypedArray;
-import android.util.AttributeSet;
-import android.util.SparseIntArray;
-import android.view.Gravity;
-import android.view.LayoutInflater;
-import android.view.View;
-import android.widget.FrameLayout;
-import android.widget.LinearLayout;
-import android.widget.TextView;
-import com.android.settingslib.R;
-
-public class UsageView extends FrameLayout {
-
- private final UsageGraph mUsageGraph;
- private final TextView[] mLabels;
- private final TextView[] mBottomLabels;
-
- public UsageView(Context context, AttributeSet attrs) {
- super(context, attrs);
- LayoutInflater.from(context).inflate(R.layout.usage_view, this);
- mUsageGraph = findViewById(R.id.usage_graph);
- mLabels = new TextView[] {
- findViewById(R.id.label_bottom),
- findViewById(R.id.label_middle),
- findViewById(R.id.label_top),
- };
- mBottomLabels = new TextView[] {
- findViewById(R.id.label_start),
- findViewById(R.id.label_end),
- };
- TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.UsageView, 0, 0);
- if (a.hasValue(R.styleable.UsageView_sideLabels)) {
- setSideLabels(a.getTextArray(R.styleable.UsageView_sideLabels));
- }
- if (a.hasValue(R.styleable.UsageView_bottomLabels)) {
- setBottomLabels(a.getTextArray(R.styleable.UsageView_bottomLabels));
- }
- if (a.hasValue(R.styleable.UsageView_textColor)) {
- int color = a.getColor(R.styleable.UsageView_textColor, 0);
- for (TextView v : mLabels) {
- v.setTextColor(color);
- }
- for (TextView v : mBottomLabels) {
- v.setTextColor(color);
- }
- }
- if (a.hasValue(R.styleable.UsageView_android_gravity)) {
- int gravity = a.getInt(R.styleable.UsageView_android_gravity, 0);
- if (gravity == Gravity.END) {
- LinearLayout layout = findViewById(R.id.graph_label_group);
- LinearLayout labels = findViewById(R.id.label_group);
- // Swap the children order.
- layout.removeView(labels);
- layout.addView(labels);
- // Set gravity.
- labels.setGravity(Gravity.END);
- // Swap the bottom space order.
- LinearLayout bottomLabels = findViewById(R.id.bottom_label_group);
- View bottomSpace = bottomLabels.findViewById(R.id.bottom_label_space);
- bottomLabels.removeView(bottomSpace);
- bottomLabels.addView(bottomSpace);
- } else if (gravity != Gravity.START) {
- throw new IllegalArgumentException("Unsupported gravity " + gravity);
- }
- }
- mUsageGraph.setAccentColor(a.getColor(R.styleable.UsageView_android_colorAccent, 0));
- }
-
- public void clearPaths() {
- mUsageGraph.clearPaths();
- }
-
- public void addPath(SparseIntArray points) {
- mUsageGraph.addPath(points);
- }
-
- public void configureGraph(int maxX, int maxY, boolean showProjection, boolean projectUp) {
- mUsageGraph.setMax(maxX, maxY);
- mUsageGraph.setShowProjection(showProjection, projectUp);
- }
-
- public void setAccentColor(int color) {
- mUsageGraph.setAccentColor(color);
- }
-
- public void setDividerLoc(int dividerLoc) {
- mUsageGraph.setDividerLoc(dividerLoc);
- }
-
- public void setDividerColors(int middleColor, int topColor) {
- mUsageGraph.setDividerColors(middleColor, topColor);
- }
-
- public void setSideLabelWeights(float before, float after) {
- setWeight(R.id.space1, before);
- setWeight(R.id.space2, after);
- }
-
- private void setWeight(int id, float weight) {
- View v = findViewById(id);
- LinearLayout.LayoutParams params = (LinearLayout.LayoutParams) v.getLayoutParams();
- params.weight = weight;
- v.setLayoutParams(params);
- }
-
- public void setSideLabels(CharSequence[] labels) {
- if (labels.length != mLabels.length) {
- throw new IllegalArgumentException("Invalid number of labels");
- }
- for (int i = 0; i < mLabels.length; i++) {
- mLabels[i].setText(labels[i]);
- }
- }
-
- public void setBottomLabels(CharSequence[] labels) {
- if (labels.length != mBottomLabels.length) {
- throw new IllegalArgumentException("Invalid number of labels");
- }
- for (int i = 0; i < mBottomLabels.length; i++) {
- mBottomLabels[i].setText(labels[i]);
- }
- }
-
-}
diff --git a/packages/SettingsLib/src/com/android/settingslib/wifi/AccessPoint.java b/packages/SettingsLib/src/com/android/settingslib/wifi/AccessPoint.java
index b3565eab79c9..c55280dc1c3e 100644
--- a/packages/SettingsLib/src/com/android/settingslib/wifi/AccessPoint.java
+++ b/packages/SettingsLib/src/com/android/settingslib/wifi/AccessPoint.java
@@ -16,6 +16,7 @@
package com.android.settingslib.wifi;
+import android.annotation.Nullable;
import android.app.AppGlobals;
import android.content.Context;
import android.content.pm.ApplicationInfo;
@@ -639,6 +640,13 @@ public class AccessPoint implements Comparable<AccessPoint> {
// Update to new summary
StringBuilder summary = new StringBuilder();
+ // TODO(b/62354743): Standardize and international delimiter usage
+ final String concatenator = " / ";
+
+ if (mBadge != NetworkBadging.BADGING_NONE) {
+ summary.append(getSpeedLabel() + concatenator);
+ }
+
if (isActive() && config != null && config.isPasspoint()) {
// This is the active connection on passpoint
summary.append(getSummary(mContext, getDetailedState(),
@@ -718,6 +726,14 @@ public class AccessPoint implements Comparable<AccessPoint> {
}
}
}
+
+ // Strip trailing delimiter if applicable
+ int concatLength = concatenator.length();
+ if (summary.length() >= concatLength && summary.substring(
+ summary.length() - concatLength, summary.length()).equals(concatenator)) {
+ summary.delete(summary.length() - concatLength, summary.length());
+ }
+
return summary.toString();
}
@@ -745,8 +761,12 @@ public class AccessPoint implements Comparable<AccessPoint> {
visibility.append(" rssi=").append(mInfo.getRssi());
visibility.append(" ");
visibility.append(" score=").append(mInfo.score);
- visibility.append(" rankingScore=").append(getRankingScore());
- visibility.append(" badge=").append(getBadge());
+ if (mRankingScore != Integer.MIN_VALUE) {
+ visibility.append(" rankingScore=").append(getRankingScore());
+ }
+ if (mBadge != NetworkBadging.BADGING_NONE) {
+ visibility.append(" speed=").append(getSpeedLabel());
+ }
visibility.append(String.format(" tx=%.1f,", mInfo.txSuccessRate));
visibility.append(String.format("%.1f,", mInfo.txRetriesRate));
visibility.append(String.format("%.1f ", mInfo.txBadRate));
@@ -1042,8 +1062,21 @@ public class AccessPoint implements Comparable<AccessPoint> {
return mRankingScore;
}
- int getBadge() {
- return mBadge;
+ int getBadge() { return mBadge;}
+
+ @Nullable
+ String getSpeedLabel() {
+ switch (mBadge) {
+ case NetworkBadging.BADGING_4K:
+ return mContext.getString(R.string.speed_label_very_fast);
+ case NetworkBadging.BADGING_HD:
+ return mContext.getString(R.string.speed_label_fast);
+ case NetworkBadging.BADGING_SD:
+ return mContext.getString(R.string.speed_label_okay);
+ case NetworkBadging.BADGING_NONE:
+ default:
+ return null;
+ }
}
/** Return true if the current RSSI is reachable, and false otherwise. */
diff --git a/packages/SettingsLib/src/com/android/settingslib/wifi/AccessPointPreference.java b/packages/SettingsLib/src/com/android/settingslib/wifi/AccessPointPreference.java
index 5361b4302b0d..f37590ec8c63 100644
--- a/packages/SettingsLib/src/com/android/settingslib/wifi/AccessPointPreference.java
+++ b/packages/SettingsLib/src/com/android/settingslib/wifi/AccessPointPreference.java
@@ -162,7 +162,10 @@ public class AccessPointPreference extends Preference {
return;
}
TronUtils.logWifiSettingsBadge(context, mWifiBadge);
- Drawable drawable = NetworkBadging.getWifiIcon(level, mWifiBadge, getContext().getTheme());
+
+ // TODO(b/62355275): Revert this to N code after deleting NetworkBadging API
+ Drawable drawable = NetworkBadging.getWifiIcon(
+ level, NetworkBadging.BADGING_NONE, getContext().getTheme());
if (!mForSavedNetworks && drawable != null) {
drawable.setTint(Utils.getColorAttr(context, android.R.attr.colorControlNormal));
setIcon(drawable);
diff --git a/packages/SettingsLib/tests/integ/src/com/android/settingslib/wifi/AccessPointTest.java b/packages/SettingsLib/tests/integ/src/com/android/settingslib/wifi/AccessPointTest.java
index 801844be87cd..9abdf88d42fb 100644
--- a/packages/SettingsLib/tests/integ/src/com/android/settingslib/wifi/AccessPointTest.java
+++ b/packages/SettingsLib/tests/integ/src/com/android/settingslib/wifi/AccessPointTest.java
@@ -19,12 +19,17 @@ import static com.google.common.truth.Truth.assertThat;
import static com.google.common.truth.Truth.assertWithMessage;
import static org.mockito.Mockito.any;
+import static org.mockito.Mockito.anyInt;
import static org.mockito.Mockito.when;
import android.content.Context;
import android.net.ConnectivityManager;
+import android.net.NetworkBadging;
import android.net.NetworkInfo;
+import android.net.NetworkKey;
+import android.net.RssiCurve;
import android.net.ScoredNetwork;
+import android.net.WifiKey;
import android.net.wifi.ScanResult;
import android.net.wifi.WifiConfiguration;
import android.net.wifi.WifiInfo;
@@ -40,6 +45,8 @@ import android.support.test.runner.AndroidJUnit4;
import android.text.SpannableString;
import android.text.style.TtsSpan;
+import com.android.settingslib.R;
+
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -55,7 +62,8 @@ public class AccessPointTest {
private static final String TEST_SSID = "test_ssid";
private Context mContext;
- @Mock private WifiNetworkScoreCache mWifiNetworkScoreCache;
+ @Mock private RssiCurve mockBadgeCurve;
+ @Mock private WifiNetworkScoreCache mockWifiNetworkScoreCache;
@Before
public void setUp() {
@@ -294,13 +302,13 @@ public class AccessPointTest {
public void testIsMetered_returnTrueWhenScoredNetworkIsMetered() {
AccessPoint ap = createAccessPointWithScanResultCache();
- when(mWifiNetworkScoreCache.getScoredNetwork(any(ScanResult.class)))
+ when(mockWifiNetworkScoreCache.getScoredNetwork(any(ScanResult.class)))
.thenReturn(
new ScoredNetwork(
null /* NetworkKey */,
null /* rssiCurve */,
true /* metered */));
- ap.update(mWifiNetworkScoreCache, false /* scoringUiEnabled */);
+ ap.update(mockWifiNetworkScoreCache, false /* scoringUiEnabled */);
assertThat(ap.isMetered()).isTrue();
}
@@ -321,6 +329,91 @@ public class AccessPointTest {
assertThat(accessPoint.isMetered()).isFalse();
}
+ @Test
+ public void testSpeedLabel_returnsVeryFastWhen4kBadgeIsSet() {
+ AccessPoint ap = createAccessPointWithScanResultCache();
+
+ when(mockWifiNetworkScoreCache.getScoredNetwork(any(ScanResult.class)))
+ .thenReturn(buildScoredNetworkWithMockBadgeCurve());
+ when(mockBadgeCurve.lookupScore(anyInt())).thenReturn((byte) NetworkBadging.BADGING_4K);
+
+ ap.update(mockWifiNetworkScoreCache, true /* scoringUiEnabled */);
+
+ assertThat(ap.getBadge()).isEqualTo(NetworkBadging.BADGING_4K);
+ assertThat(ap.getSpeedLabel())
+ .isEqualTo(mContext.getString(R.string.speed_label_very_fast));
+ }
+
+ @Test
+ public void testSpeedLabel_returnsFastWhenHdBadgeIsSet() {
+ AccessPoint ap = createAccessPointWithScanResultCache();
+
+ when(mockWifiNetworkScoreCache.getScoredNetwork(any(ScanResult.class)))
+ .thenReturn(buildScoredNetworkWithMockBadgeCurve());
+ when(mockBadgeCurve.lookupScore(anyInt())).thenReturn((byte) NetworkBadging.BADGING_HD);
+
+ ap.update(mockWifiNetworkScoreCache, true /* scoringUiEnabled */);
+
+ assertThat(ap.getBadge()).isEqualTo(NetworkBadging.BADGING_HD);
+ assertThat(ap.getSpeedLabel())
+ .isEqualTo(mContext.getString(R.string.speed_label_fast));
+ }
+
+ @Test
+ public void testSpeedLabel_returnsOkayWhenSdBadgeIsSet() {
+ AccessPoint ap = createAccessPointWithScanResultCache();
+
+ when(mockWifiNetworkScoreCache.getScoredNetwork(any(ScanResult.class)))
+ .thenReturn(buildScoredNetworkWithMockBadgeCurve());
+ when(mockBadgeCurve.lookupScore(anyInt())).thenReturn((byte) NetworkBadging.BADGING_SD);
+
+ ap.update(mockWifiNetworkScoreCache, true /* scoringUiEnabled */);
+
+ assertThat(ap.getBadge()).isEqualTo(NetworkBadging.BADGING_SD);
+ assertThat(ap.getSpeedLabel())
+ .isEqualTo(mContext.getString(R.string.speed_label_okay));
+ }
+
+ @Test
+ public void testSummaryString_showsSpeedLabel() {
+ AccessPoint ap = createAccessPointWithScanResultCache();
+
+ when(mockWifiNetworkScoreCache.getScoredNetwork(any(ScanResult.class)))
+ .thenReturn(buildScoredNetworkWithMockBadgeCurve());
+ when(mockBadgeCurve.lookupScore(anyInt())).thenReturn((byte) NetworkBadging.BADGING_4K);
+
+ ap.update(mockWifiNetworkScoreCache, true /* scoringUiEnabled */);
+
+ assertThat(ap.getSummary()).isEqualTo(mContext.getString(R.string.speed_label_very_fast));
+ }
+
+ @Test
+ public void testSummaryString_concatenatesSpeedLabel() {
+ AccessPoint ap = createAccessPointWithScanResultCache();
+ ap.update(new WifiConfiguration());
+
+ when(mockWifiNetworkScoreCache.getScoredNetwork(any(ScanResult.class)))
+ .thenReturn(buildScoredNetworkWithMockBadgeCurve());
+ when(mockBadgeCurve.lookupScore(anyInt())).thenReturn((byte) NetworkBadging.BADGING_4K);
+
+ ap.update(mockWifiNetworkScoreCache, true /* scoringUiEnabled */);
+
+ String expectedString = mContext.getString(R.string.speed_label_very_fast) + " / "
+ + mContext.getString(R.string.wifi_remembered);
+ assertThat(ap.getSummary()).isEqualTo(expectedString);
+ }
+
+ private ScoredNetwork buildScoredNetworkWithMockBadgeCurve() {
+ Bundle attr1 = new Bundle();
+ attr1.putParcelable(ScoredNetwork.ATTRIBUTES_KEY_BADGING_CURVE, mockBadgeCurve);
+ return new ScoredNetwork(
+ new NetworkKey(new WifiKey("\"ssid\"", "00:00:00:00:00:00")),
+ mockBadgeCurve,
+ false /* meteredHint */,
+ attr1);
+
+ }
+
private AccessPoint createAccessPointWithScanResultCache() {
Bundle bundle = new Bundle();
ArrayList<ScanResult> scanResults = new ArrayList<>();
@@ -333,7 +426,7 @@ public class AccessPointTest {
scanResults.add(scanResult);
}
- bundle.putParcelableArrayList("key_scanresultcache", scanResults);
+ bundle.putParcelableArrayList(AccessPoint.KEY_SCANRESULTCACHE, scanResults);
return new AccessPoint(mContext, bundle);
}
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/graph/BottomLabelLayoutTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/graph/BottomLabelLayoutTest.java
deleted file mode 100644
index ec217230af95..000000000000
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/graph/BottomLabelLayoutTest.java
+++ /dev/null
@@ -1,70 +0,0 @@
-/*
- * Copyright (C) 2017 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.settingslib.graph;
-
-import static com.google.common.truth.Truth.assertThat;
-
-import android.content.Context;
-import android.view.View;
-import android.widget.LinearLayout;
-import android.widget.Space;
-
-import com.android.settingslib.R;
-import com.android.settingslib.TestConfig;
-
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.robolectric.RobolectricTestRunner;
-import org.robolectric.RuntimeEnvironment;
-import org.robolectric.annotation.Config;
-
-@RunWith(RobolectricTestRunner.class)
-@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
-public class BottomLabelLayoutTest {
- private BottomLabelLayout mBottomLabelLayout;
- private Context mContext;
- private Space mSpace;
-
- @Before
- public void setUp() {
- mContext = RuntimeEnvironment.application;
- mBottomLabelLayout = new BottomLabelLayout(mContext, null);
- mBottomLabelLayout.setOrientation(LinearLayout.HORIZONTAL);
-
- mSpace = new Space(mContext);
- mSpace.setId(R.id.spacer);
- mBottomLabelLayout.addView(mSpace);
- }
-
- @Test
- public void testSetStacked_stackedTrue_layoutVertical() {
- mBottomLabelLayout.setStacked(true);
-
- assertThat(mBottomLabelLayout.getOrientation()).isEqualTo(LinearLayout.VERTICAL);
- assertThat(mSpace.getVisibility()).isEqualTo(View.GONE);
- }
-
- @Test
- public void testSetStacked_stackedFalse_layoutHorizontal() {
- mBottomLabelLayout.setStacked(false);
-
- assertThat(mBottomLabelLayout.getOrientation()).isEqualTo(LinearLayout.HORIZONTAL);
- assertThat(mSpace.getVisibility()).isEqualTo(View.VISIBLE);
- }
-}
diff --git a/packages/SystemUI/colorextraction/src/com/google/android/colorextraction/ColorExtractor.java b/packages/SystemUI/colorextraction/src/com/google/android/colorextraction/ColorExtractor.java
index 1b3519b1d4c2..4a5d8b460517 100644
--- a/packages/SystemUI/colorextraction/src/com/google/android/colorextraction/ColorExtractor.java
+++ b/packages/SystemUI/colorextraction/src/com/google/android/colorextraction/ColorExtractor.java
@@ -19,9 +19,10 @@ package com.google.android.colorextraction;
import android.app.WallpaperColors;
import android.app.WallpaperManager;
import android.content.Context;
-import android.graphics.Color;
-import android.support.v4.graphics.ColorUtils;
+import android.support.annotation.NonNull;
+import android.support.annotation.VisibleForTesting;
import android.util.Log;
+import android.util.SparseArray;
import com.google.android.colorextraction.types.ExtractionType;
import com.google.android.colorextraction.types.Tonal;
@@ -32,81 +33,143 @@ import java.util.ArrayList;
* Class to process wallpaper colors and generate a tonal palette based on them.
*/
public class ColorExtractor implements WallpaperManager.OnColorsChangedListener {
+
+ public static final int TYPE_NORMAL = 0;
+ public static final int TYPE_DARK = 1;
+ public static final int TYPE_EXTRA_DARK = 2;
+ private static final int[] sGradientTypes = new int[]{TYPE_NORMAL, TYPE_DARK, TYPE_EXTRA_DARK};
+
private static final String TAG = "ColorExtractor";
- private static final int FALLBACK_COLOR = Color.BLACK;
- private static final float DARK_TEXT_LUMINOSITY = 0.7f;
+
+ @VisibleForTesting
+ static final int FALLBACK_COLOR = 0xff83888d;
private int mMainFallbackColor = FALLBACK_COLOR;
private int mSecondaryFallbackColor = FALLBACK_COLOR;
- private final GradientColors mSystemColors;
- private final GradientColors mLockColors;
+ private final SparseArray<GradientColors[]> mGradientColors;
+ private final ArrayList<OnColorsChangedListener> mOnColorsChangedListeners;
+ // Colors to return when the wallpaper isn't visible
+ private final GradientColors mWpHiddenColors;
private final Context mContext;
private final ExtractionType mExtractionType;
- private final ArrayList<OnColorsChangedListener> mOnColorsChangedListeners;
public ColorExtractor(Context context) {
+ this(context, new Tonal());
+ }
+
+ @VisibleForTesting
+ public ColorExtractor(Context context, ExtractionType extractionType) {
mContext = context;
- mSystemColors = new GradientColors();
- mLockColors = new GradientColors();
- mExtractionType = new Tonal();
+ mWpHiddenColors = new GradientColors();
+ mWpHiddenColors.setMainColor(FALLBACK_COLOR);
+ mWpHiddenColors.setSecondaryColor(FALLBACK_COLOR);
+ mExtractionType = extractionType;
+
+ mGradientColors = new SparseArray<>();
+ for (int which : new int[] { WallpaperManager.FLAG_LOCK, WallpaperManager.FLAG_SYSTEM}) {
+ GradientColors[] colors = new GradientColors[sGradientTypes.length];
+ mGradientColors.append(which, colors);
+ for (int type : sGradientTypes) {
+ colors[type] = new GradientColors();
+ }
+ }
+
mOnColorsChangedListeners = new ArrayList<>();
WallpaperManager wallpaperManager = mContext.getSystemService(WallpaperManager.class);
-
if (wallpaperManager == null) {
Log.w(TAG, "Can't listen to color changes!");
} else {
wallpaperManager.addOnColorsChangedListener(this);
+
+ // Initialize all gradients with the current colors
+ GradientColors[] systemColors = mGradientColors.get(WallpaperManager.FLAG_SYSTEM);
extractInto(wallpaperManager.getWallpaperColors(WallpaperManager.FLAG_SYSTEM),
- mSystemColors);
+ systemColors[TYPE_NORMAL],
+ systemColors[TYPE_DARK],
+ systemColors[TYPE_EXTRA_DARK]);
+
+ GradientColors[] lockColors = mGradientColors.get(WallpaperManager.FLAG_LOCK);
extractInto(wallpaperManager.getWallpaperColors(WallpaperManager.FLAG_LOCK),
- mLockColors);
+ lockColors[TYPE_NORMAL],
+ lockColors[TYPE_DARK],
+ lockColors[TYPE_EXTRA_DARK]);
}
}
+ /**
+ * Retrieve TYPE_NORMAL gradient colors considering wallpaper visibility.
+ *
+ * @param which FLAG_LOCK or FLAG_SYSTEM
+ * @return colors
+ */
+ @NonNull
public GradientColors getColors(int which) {
- if (which == WallpaperManager.FLAG_LOCK) {
- return mLockColors;
- } else if (which == WallpaperManager.FLAG_SYSTEM) {
- return mSystemColors;
- } else {
- throw new IllegalArgumentException("which should be either FLAG_SYSTEM or FLAG_LOCK");
+ return getColors(which, TYPE_NORMAL);
+ }
+
+ /**
+ * Get current gradient colors for one of the possible gradient types
+ *
+ * @param which FLAG_LOCK or FLAG_SYSTEM
+ * @param type TYPE_NORMAL, TYPE_DARK or TYPE_EXTRA_DARK
+ * @return colors
+ */
+ public GradientColors getColors(int which, int type) {
+ if (type != TYPE_NORMAL && type != TYPE_DARK && type != TYPE_EXTRA_DARK) {
+ throw new IllegalArgumentException(
+ "type should be TYPE_NORMAL, TYPE_DARK or TYPE_EXTRA_DARK");
}
+ if (which != WallpaperManager.FLAG_LOCK && which != WallpaperManager.FLAG_SYSTEM) {
+ throw new IllegalArgumentException("which should be FLAG_SYSTEM or FLAG_NORMAL");
+ }
+
+ return mGradientColors.get(which)[type];
}
@Override
public void onColorsChanged(WallpaperColors colors, int which) {
+ boolean changed = false;
if ((which & WallpaperManager.FLAG_LOCK) != 0) {
- extractInto(colors, mLockColors);
- for (OnColorsChangedListener listener : mOnColorsChangedListeners) {
- listener.onColorsChanged(mLockColors, WallpaperManager.FLAG_LOCK);
- }
+ GradientColors[] lockColors = mGradientColors.get(WallpaperManager.FLAG_LOCK);
+ extractInto(colors, lockColors[TYPE_NORMAL], lockColors[TYPE_DARK],
+ lockColors[TYPE_EXTRA_DARK]);
+
+ changed = true;
}
if ((which & WallpaperManager.FLAG_SYSTEM) != 0) {
- extractInto(colors, mSystemColors);
- for (OnColorsChangedListener listener : mOnColorsChangedListeners) {
- listener.onColorsChanged(mSystemColors, WallpaperManager.FLAG_SYSTEM);
- }
+ GradientColors[] systemColors = mGradientColors.get(WallpaperManager.FLAG_SYSTEM);
+ extractInto(colors, systemColors[TYPE_NORMAL], systemColors[TYPE_DARK],
+ systemColors[TYPE_EXTRA_DARK]);
+ changed = true;
+ }
+
+ if (changed) {
+ triggerColorsChanged(which);
+ }
+ }
+
+ private void triggerColorsChanged(int which) {
+ for (OnColorsChangedListener listener: mOnColorsChangedListeners) {
+ listener.onColorsChanged(this, which);
}
}
- private void extractInto(WallpaperColors inWallpaperColors, GradientColors outGradientColors) {
- applyFallback(outGradientColors);
+ private void extractInto(WallpaperColors inWallpaperColors,
+ GradientColors outGradientColorsNormal, GradientColors outGradientColorsDark,
+ GradientColors outGradientColorsExtraDark) {
if (inWallpaperColors == null) {
+ applyFallback(outGradientColorsNormal);
+ applyFallback(outGradientColorsDark);
+ applyFallback(outGradientColorsExtraDark);
return;
}
- boolean success = mExtractionType.extractInto(inWallpaperColors, outGradientColors);
- if (success) {
- // Updating dark text support. We're going to verify if the mean luminosity
- // is greater then a threshold.
- float hsl[] = new float[3];
- float meanLuminosity = 0;
- ColorUtils.colorToHSL(outGradientColors.getMainColor(), hsl);
- meanLuminosity += hsl[2];
- ColorUtils.colorToHSL(outGradientColors.getSecondaryColor(), hsl);
- meanLuminosity += hsl[2];
- meanLuminosity /= 2;
- outGradientColors.setSupportsDarkText(meanLuminosity >= DARK_TEXT_LUMINOSITY);
+ boolean success = mExtractionType.extractInto(inWallpaperColors, outGradientColorsNormal,
+ outGradientColorsDark, outGradientColorsExtraDark);
+ if (!success) {
+ applyFallback(outGradientColorsNormal);
+ applyFallback(outGradientColorsDark);
+ applyFallback(outGradientColorsExtraDark);
}
}
@@ -123,11 +186,11 @@ public class ColorExtractor implements WallpaperManager.OnColorsChangedListener
}
}
- public void addOnColorsChangedListener(OnColorsChangedListener listener) {
+ public void addOnColorsChangedListener(@NonNull OnColorsChangedListener listener) {
mOnColorsChangedListeners.add(listener);
}
- public void removeOnColorsChangedListener(OnColorsChangedListener listener) {
+ public void removeOnColorsChangedListener(@NonNull OnColorsChangedListener listener) {
mOnColorsChangedListeners.remove(listener);
}
@@ -184,9 +247,15 @@ public class ColorExtractor implements WallpaperManager.OnColorsChangedListener
code = 31 * code + (mSupportsDarkText ? 0 : 1);
return code;
}
+
+ @Override
+ public String toString() {
+ return "GradientColors(" + Integer.toHexString(mMainColor) + ", "
+ + Integer.toHexString(mSecondaryColor) + ")";
+ }
}
public interface OnColorsChangedListener {
- void onColorsChanged(GradientColors colors, int which);
+ void onColorsChanged(ColorExtractor colorExtractor, int which);
}
}
diff --git a/packages/SystemUI/colorextraction/src/com/google/android/colorextraction/types/ExtractionType.java b/packages/SystemUI/colorextraction/src/com/google/android/colorextraction/types/ExtractionType.java
index 36cabc999720..4c3ac3e038de 100644
--- a/packages/SystemUI/colorextraction/src/com/google/android/colorextraction/types/ExtractionType.java
+++ b/packages/SystemUI/colorextraction/src/com/google/android/colorextraction/types/ExtractionType.java
@@ -29,10 +29,19 @@ public interface ExtractionType {
* Executes color extraction by reading WallpaperColors and setting
* main and secondary colors on GradientColors.
*
+ * Extraction is expected to happen with 3 different gradient types:
+ * Normal, with the main extracted colors
+ * Dark, with extra contrast
+ * ExtraDark, for places where GAR is mandatory, like the emergency dialer
+ *
* @param inWallpaperColors where to read from
- * @param outGradientColors object that should receive the colors
- * @return true if successful
+ * @param outGradientColorsNormal object that should receive normal colors
+ * @param outGradientColorsDark object that should receive dark colors
+ * @param outGradientColorsExtraDark object that should receive extra dark colors
+ * @return true if successful.
*/
boolean extractInto(WallpaperColors inWallpaperColors,
- ColorExtractor.GradientColors outGradientColors);
+ ColorExtractor.GradientColors outGradientColorsNormal,
+ ColorExtractor.GradientColors outGradientColorsDark,
+ ColorExtractor.GradientColors outGradientColorsExtraDark);
}
diff --git a/packages/SystemUI/colorextraction/src/com/google/android/colorextraction/types/Tonal.java b/packages/SystemUI/colorextraction/src/com/google/android/colorextraction/types/Tonal.java
index 85ac90a53ea8..5b4b3ed77f3a 100644
--- a/packages/SystemUI/colorextraction/src/com/google/android/colorextraction/types/Tonal.java
+++ b/packages/SystemUI/colorextraction/src/com/google/android/colorextraction/types/Tonal.java
@@ -27,7 +27,7 @@ import android.util.MathUtils;
import android.util.Pair;
import android.util.Range;
-import com.google.android.colorextraction.ColorExtractor;
+import com.google.android.colorextraction.ColorExtractor.GradientColors;
/**
* Implementation of tonal color extraction
@@ -43,25 +43,25 @@ public class Tonal implements ExtractionType {
// When extracting the main color, only consider colors
// present in at least MIN_COLOR_OCCURRENCE of the image
private static final float MIN_COLOR_OCCURRENCE = 0.1f;
+ private static final boolean DEBUG = true;
- // Secondary color will be darker than the main color when
- // main color is brighter than this variable.
- private static final float MAX_COLOR_LUMINOSITY = 0.8f;
- // Luminosity difference between main and secondary colors
- // should never be greater then this.
- private static final float MAX_LUMINOSITY_DISTANCE = 0.35f;
+ // Temporary variable to avoid allocations
+ private float[] mTmpHSL = new float[3];
/**
* Grab colors from WallpaperColors as set them into GradientColors
*
- * @param wallpaperColors input
- * @param gradientColors output
+ * @param inWallpaperColors input
+ * @param outColorsNormal colors for normal theme
+ * @param outColorsDark colors for dar theme
+ * @param outColorsExtraDark colors for extra dark theme
* @return true if successful
*/
- public boolean extractInto(WallpaperColors wallpaperColors,
- ColorExtractor.GradientColors gradientColors) {
+ public boolean extractInto(@NonNull WallpaperColors inWallpaperColors,
+ @NonNull GradientColors outColorsNormal, @NonNull GradientColors outColorsDark,
+ @NonNull GradientColors outColorsExtraDark) {
- if (wallpaperColors.getColors().size() == 0) {
+ if (inWallpaperColors.getColors().size() == 0) {
return false;
}
// Tonal is not really a sort, it takes a color from the extracted
@@ -70,17 +70,17 @@ public class Tonal implements ExtractionType {
// and replaces the original palette
// First find the most representative color in the image
- populationSort(wallpaperColors);
+ populationSort(inWallpaperColors);
// Calculate total
int total = 0;
- for (Pair<Color, Integer> weightedColor : wallpaperColors.getColors()) {
+ for (Pair<Color, Integer> weightedColor : inWallpaperColors.getColors()) {
total += weightedColor.second;
}
// Get bright colors that occur often enough in this image
Pair<Color, Integer> bestColor = null;
float[] hsl = new float[3];
- for (Pair<Color, Integer> weightedColor : wallpaperColors.getColors()) {
+ for (Pair<Color, Integer> weightedColor : inWallpaperColors.getColors()) {
float colorOccurrence = weightedColor.second / (float) total;
if (colorOccurrence < MIN_COLOR_OCCURRENCE) {
break;
@@ -97,7 +97,7 @@ public class Tonal implements ExtractionType {
}
}
- // Fallback to first color
+ // Fail if not found
if (bestColor == null) {
return false;
}
@@ -107,59 +107,97 @@ public class Tonal implements ExtractionType {
hsl);
// The Android HSL definition requires the hue to go from 0 to 360 but
- // the Material Tonal Palette defines hues from 0 to 1
- hsl[0] /= 360.0f; // normalize
+ // the Material Tonal Palette defines hues from 0 to 1.
+ hsl[0] /= 360f;
// Find the palette that contains the closest color
TonalPalette palette = findTonalPalette(hsl[0]);
-
if (palette == null) {
Log.w(TAG, "Could not find a tonal palette!");
return false;
}
+ // Figure out what's the main color index in the optimal palette
int fitIndex = bestFit(palette, hsl[0], hsl[1], hsl[2]);
if (fitIndex == -1) {
Log.w(TAG, "Could not find best fit!");
return false;
}
+
+ // Generate the 10 colors palette by offsetting each one of them
float[] h = fit(palette.h, hsl[0], fitIndex,
Float.NEGATIVE_INFINITY, Float.POSITIVE_INFINITY);
float[] s = fit(palette.s, hsl[1], fitIndex, 0.0f, 1.0f);
float[] l = fit(palette.l, hsl[2], fitIndex, 0.0f, 1.0f);
- hsl[0] = fract(h[fitIndex]) * 360.0f;
- hsl[1] = s[fitIndex];
- hsl[2] = l[fitIndex];
- gradientColors.setMainColor(ColorUtils.HSLToColor(hsl));
-
- int secondColorIndex = fitIndex;
- if (hsl[2] > MAX_COLOR_LUMINOSITY) {
- for (int i = secondColorIndex - 1; i >= 0; i--) {
- float distance = Math.abs(hsl[2] - l[i]);
- if (distance > MAX_LUMINOSITY_DISTANCE) {
- break;
- }
- secondColorIndex = i;
- }
- } else {
- for (int i = secondColorIndex + 1; i < h.length; i++) {
- float distance = Math.abs(hsl[2] - l[i]);
- if (distance > MAX_LUMINOSITY_DISTANCE) {
- break;
+ final int textInversionIndex = h.length - 3;
+ if (DEBUG) {
+ StringBuilder builder = new StringBuilder("Tonal Palette - index: " + fitIndex +
+ ". Main color: " + Integer.toHexString(getColorInt(fitIndex, h, s, l)) +
+ "\nColors: ");
+
+ for (int i=0; i < h.length; i++) {
+ builder.append(Integer.toHexString(getColorInt(i, h, s, l)));
+ if (i < h.length - 1) {
+ builder.append(", ");
}
- secondColorIndex = i;
}
+ Log.d(TAG, builder.toString());
}
- hsl[0] = fract(h[secondColorIndex]) * 360.0f;
- hsl[1] = s[secondColorIndex];
- hsl[2] = l[secondColorIndex];
- gradientColors.setSecondaryColor(ColorUtils.HSLToColor(hsl));
+ // Normal colors:
+ // best fit + a 2 colors offset
+ int primaryIndex = fitIndex;
+ int secondaryIndex = primaryIndex + (primaryIndex >= 2 ? -2 : 2);
+ outColorsNormal.setMainColor(getColorInt(primaryIndex, h, s, l));
+ outColorsNormal.setSecondaryColor(getColorInt(secondaryIndex, h, s, l));
+
+ // Dark colors:
+ // Stops at 4th color, only lighter if dark text is supported
+ if (fitIndex < 2) {
+ primaryIndex = 0;
+ } else if (fitIndex < textInversionIndex) {
+ primaryIndex = Math.min(fitIndex, 3);
+ } else {
+ primaryIndex = h.length - 1;
+ }
+ secondaryIndex = primaryIndex + (primaryIndex >= 2 ? -2 : 2);
+ outColorsDark.setMainColor(getColorInt(primaryIndex, h, s, l));
+ outColorsDark.setSecondaryColor(getColorInt(secondaryIndex, h, s, l));
+
+ // Extra Dark:
+ // Stay close to dark colors until dark text is supported
+ if (fitIndex < 2) {
+ primaryIndex = 0;
+ } else if (fitIndex < textInversionIndex) {
+ primaryIndex = 2;
+ } else {
+ primaryIndex = h.length - 1;
+ }
+ secondaryIndex = primaryIndex + (primaryIndex >= 2 ? -2 : 2);
+ outColorsExtraDark.setMainColor(getColorInt(primaryIndex, h, s, l));
+ outColorsExtraDark.setSecondaryColor(getColorInt(secondaryIndex, h, s, l));
+
+ final boolean supportsDarkText = fitIndex >= textInversionIndex;
+ outColorsNormal.setSupportsDarkText(supportsDarkText);
+ outColorsDark.setSupportsDarkText(supportsDarkText);
+ outColorsExtraDark.setSupportsDarkText(supportsDarkText);
+
+ if (DEBUG) {
+ Log.d(TAG, "Gradients: \n\tNormal " + outColorsNormal + "\n\tDark " + outColorsDark
+ + "\n\tExtra dark: " + outColorsExtraDark);
+ }
return true;
}
+ private int getColorInt(int fitIndex, float[] h, float[] s, float[] l) {
+ mTmpHSL[0] = fract(h[fitIndex]) * 360.0f;
+ mTmpHSL[1] = s[fitIndex];
+ mTmpHSL[2] = l[fitIndex];
+ return ColorUtils.HSLToColor(mTmpHSL);
+ }
+
/**
* Checks if a given color exists in the blacklist
* @param hsl float array with 3 components (H 0..360, S 0..1 and L 0..1)
diff --git a/packages/SystemUI/colorextraction/tests/src/com/google/android/colorextraction/ColorExtractorTest.java b/packages/SystemUI/colorextraction/tests/src/com/google/android/colorextraction/ColorExtractorTest.java
new file mode 100644
index 000000000000..fd698d050a0c
--- /dev/null
+++ b/packages/SystemUI/colorextraction/tests/src/com/google/android/colorextraction/ColorExtractorTest.java
@@ -0,0 +1,114 @@
+/*
+ * Copyright (C) 2017 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.google.android.colorextraction;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+
+import android.app.WallpaperColors;
+import android.app.WallpaperManager;
+import android.content.Context;
+import android.graphics.Color;
+import android.support.test.InstrumentationRegistry;
+import android.support.test.filters.SmallTest;
+import android.support.test.runner.AndroidJUnit4;
+
+import com.google.android.colorextraction.ColorExtractor.GradientColors;
+import com.google.android.colorextraction.types.ExtractionType;
+import com.google.android.colorextraction.types.Tonal;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+/**
+ * Tests tonal palette generation.
+ */
+@SmallTest
+@RunWith(AndroidJUnit4.class)
+public class ColorExtractorTest {
+
+ Context mContext;
+
+ @Before
+ public void setup() {
+ mContext = InstrumentationRegistry.getContext();
+ }
+
+ @Test
+ public void ColorExtractor_extractWhenInitialized() {
+ ExtractionType type = mock(Tonal.class);
+ new ColorExtractor(mContext, type);
+ // 1 for lock and 1 for system
+ verify(type, times(2))
+ .extractInto(any(), any(), any(), any());
+ }
+
+ @Test
+ public void getColors_usesFallbackIfFails() {
+ ExtractionType alwaysFail =
+ (inWallpaperColors, outGradientColorsNormal, outGradientColorsDark,
+ outGradientColorsExtraDark) -> false;
+ ColorExtractor extractor = new ColorExtractor(mContext, alwaysFail);
+ GradientColors colors = extractor.getColors(WallpaperManager.FLAG_SYSTEM);
+
+ assertEquals("Should be using the fallback color.",
+ colors.getMainColor(), ColorExtractor.FALLBACK_COLOR);
+ assertEquals("Should be using the fallback color.",
+ colors.getSecondaryColor(), ColorExtractor.FALLBACK_COLOR);
+ assertFalse("Dark text support should be false.", colors.supportsDarkText());
+ }
+
+ @Test
+ public void getColors_usesExtractedColors() {
+ GradientColors colorsExpectedNormal = new GradientColors();
+ colorsExpectedNormal.setMainColor(Color.RED);
+ colorsExpectedNormal.setSecondaryColor(Color.GRAY);
+
+ GradientColors colorsExpectedDark = new GradientColors();
+ colorsExpectedNormal.setMainColor(Color.BLACK);
+ colorsExpectedNormal.setSecondaryColor(Color.BLUE);
+
+ GradientColors colorsExpectedExtraDark = new GradientColors();
+ colorsExpectedNormal.setMainColor(Color.MAGENTA);
+ colorsExpectedNormal.setSecondaryColor(Color.GREEN);
+
+ ExtractionType type =
+ (inWallpaperColors, outGradientColorsNormal, outGradientColorsDark,
+ outGradientColorsExtraDark) -> {
+ outGradientColorsNormal.set(colorsExpectedNormal);
+ outGradientColorsDark.set(colorsExpectedDark);
+ outGradientColorsExtraDark.set(colorsExpectedExtraDark);
+ // Successful extraction
+ return true;
+ };
+ ColorExtractor extractor = new ColorExtractor(mContext, type);
+
+ assertEquals("Extracted colors not being used!",
+ extractor.getColors(WallpaperManager.FLAG_SYSTEM, ColorExtractor.TYPE_NORMAL),
+ colorsExpectedNormal);
+ assertEquals("Extracted colors not being used!",
+ extractor.getColors(WallpaperManager.FLAG_SYSTEM, ColorExtractor.TYPE_DARK),
+ colorsExpectedDark);
+ assertEquals("Extracted colors not being used!",
+ extractor.getColors(WallpaperManager.FLAG_SYSTEM, ColorExtractor.TYPE_EXTRA_DARK),
+ colorsExpectedExtraDark);
+ }
+}
diff --git a/packages/SystemUI/colorextraction/tests/src/com/google/android/colorextraction/types/TonalTest.java b/packages/SystemUI/colorextraction/tests/src/com/google/android/colorextraction/types/TonalTest.java
index 537ee1ac2fae..404076cb5301 100644
--- a/packages/SystemUI/colorextraction/tests/src/com/google/android/colorextraction/types/TonalTest.java
+++ b/packages/SystemUI/colorextraction/tests/src/com/google/android/colorextraction/types/TonalTest.java
@@ -27,6 +27,7 @@ import android.util.Pair;
import android.util.Range;
import com.google.android.colorextraction.ColorExtractor;
+import com.google.android.colorextraction.ColorExtractor.GradientColors;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -76,7 +77,8 @@ public class TonalTest {
// Make sure that palette generation will fail
Tonal tonal = new Tonal();
- boolean success = tonal.extractInto(colors, new ColorExtractor.GradientColors());
+ boolean success = tonal.extractInto(colors, new GradientColors(), new GradientColors(),
+ new GradientColors());
assertFalse("Cannot generate a tonal palette from blacklisted colors ", success);
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialog.java b/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialog.java
index ae6249d57599..e8dcf6c1f0b2 100644
--- a/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialog.java
+++ b/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialog.java
@@ -1339,14 +1339,14 @@ class GlobalActionsDialog implements DialogInterface.OnDismissListener, DialogIn
}
@Override
- public void onColorsChanged(GradientColors colors, int which) {
+ public void onColorsChanged(ColorExtractor extractor, int which) {
if (mKeyguardShowing) {
if ((WallpaperManager.FLAG_LOCK & which) != 0) {
- mGradientDrawable.setColors(colors);
+ mGradientDrawable.setColors(extractor.getColors(WallpaperManager.FLAG_LOCK));
}
} else {
if ((WallpaperManager.FLAG_SYSTEM & which) != 0) {
- mGradientDrawable.setColors(colors);
+ mGradientDrawable.setColors(extractor.getColors(WallpaperManager.FLAG_SYSTEM));
}
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java b/packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java
index 978533cfdf56..319b4638713a 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java
@@ -21,6 +21,7 @@ import static android.app.ActivityManager.StackId.INVALID_STACK_ID;
import android.animation.Animator;
import android.animation.ObjectAnimator;
import android.app.ActivityOptions.OnAnimationStartedListener;
+import android.app.WallpaperColors;
import android.app.WallpaperManager;
import android.content.Context;
import android.graphics.Canvas;
@@ -111,7 +112,7 @@ public class RecentsView extends FrameLayout implements ColorExtractor.OnColorsC
private int mDividerSize;
private final float mScrimAlpha;
- private final GradientDrawable mBackgroundScrim;
+ private GradientDrawable mBackgroundScrim;
private final ColorExtractor mColorExtractor;
private Animator mBackgroundScrimAnimator;
@@ -828,9 +829,9 @@ public class RecentsView extends FrameLayout implements ColorExtractor.OnColorsC
}
@Override
- public void onColorsChanged(ColorExtractor.GradientColors colors, int which) {
+ public void onColorsChanged(ColorExtractor extractor, int which) {
if ((which & WallpaperManager.FLAG_SYSTEM) != 0) {
- mBackgroundScrim.setColors(colors);
+ mBackgroundScrim.setColors(extractor.getColors(WallpaperManager.FLAG_SYSTEM));
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/SignalClusterView.java b/packages/SystemUI/src/com/android/systemui/statusbar/SignalClusterView.java
index 18cc8721ff95..22192db95c76 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/SignalClusterView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/SignalClusterView.java
@@ -28,6 +28,7 @@ import android.graphics.drawable.Animatable;
import android.graphics.drawable.AnimatedVectorDrawable;
import android.graphics.drawable.Drawable;
import android.graphics.drawable.LayerDrawable;
+import android.net.NetworkBadging;
import android.telephony.SubscriptionInfo;
import android.util.ArraySet;
import android.util.AttributeSet;
@@ -581,10 +582,11 @@ public class SignalClusterView extends LinearLayout implements NetworkController
*/
private void setBadgedWifiIconForView(ImageView imageView, @DrawableRes int wifiPieId,
@DrawableRes int badgeId) {
+ // TODO(sghuman): Delete this method and revert to N badging logic
// Using the imageView's context to retrieve the Drawable so that theme is preserved.;
LayerDrawable icon = new LayerDrawable(new Drawable[] {
imageView.getContext().getDrawable(wifiPieId),
- imageView.getContext().getDrawable(badgeId)});
+ imageView.getContext().getDrawable(NetworkBadging.BADGING_NONE)});
// The LayerDrawable shares an underlying state so we must mutate the object to change the
// color between the light and dark themes.
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java
index 69f5135d406f..f502bb5c5dfc 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java
@@ -25,7 +25,6 @@ import android.content.Context;
import android.graphics.Color;
import android.graphics.Rect;
import android.graphics.drawable.Drawable;
-import android.util.Log;
import android.util.MathUtils;
import android.view.View;
import android.view.ViewGroup;
@@ -44,13 +43,14 @@ import com.android.systemui.statusbar.policy.OnHeadsUpChangedListener;
import com.android.systemui.statusbar.stack.ViewState;
import com.google.android.colorextraction.ColorExtractor;
+import com.google.android.colorextraction.ColorExtractor.OnColorsChangedListener;
/**
* Controls both the scrim behind the notifications and in front of the notifications (when a
* security method gets shown).
*/
public class ScrimController implements ViewTreeObserver.OnPreDrawListener,
- OnHeadsUpChangedListener, ColorExtractor.OnColorsChangedListener {
+ OnHeadsUpChangedListener, OnColorsChangedListener {
public static final long ANIMATION_DURATION = 220;
public static final Interpolator KEYGUARD_FADE_OUT_INTERPOLATOR
= new PathInterpolator(0f, 0, 0.7f, 1f);
@@ -80,7 +80,9 @@ public class ScrimController implements ViewTreeObserver.OnPreDrawListener,
private final ColorExtractor mColorExtractor;
private ColorExtractor.GradientColors mLockColors;
+ private ColorExtractor.GradientColors mLockColorsDark;
private ColorExtractor.GradientColors mSystemColors;
+ private ColorExtractor.GradientColors mSystemColorsDark;
private boolean mNeedsDrawableColorUpdate;
protected float mScrimBehindAlpha;
@@ -133,6 +135,11 @@ public class ScrimController implements ViewTreeObserver.OnPreDrawListener,
mColorExtractor.addOnColorsChangedListener(this);
mLockColors = mColorExtractor.getColors(WallpaperManager.FLAG_LOCK);
mSystemColors = mColorExtractor.getColors(WallpaperManager.FLAG_SYSTEM);
+ // Darker gradient for the top scrim (mScrimInFront)
+ mLockColorsDark = mColorExtractor.getColors(WallpaperManager.FLAG_LOCK,
+ ColorExtractor.TYPE_DARK);
+ mSystemColorsDark = mColorExtractor.getColors(WallpaperManager.FLAG_SYSTEM,
+ ColorExtractor.TYPE_DARK);
mNeedsDrawableColorUpdate = true;
updateHeadsUpScrim(false);
@@ -142,8 +149,7 @@ public class ScrimController implements ViewTreeObserver.OnPreDrawListener,
public void setKeyguardShowing(boolean showing) {
mKeyguardShowing = showing;
- // Showing/hiding the keyguard means that scrim colors
- // will probably have to be switched
+ // Showing/hiding the keyguard means that scrim colors have to be switched
mNeedsDrawableColorUpdate = true;
scheduleUpdate();
}
@@ -301,11 +307,15 @@ public class ScrimController implements ViewTreeObserver.OnPreDrawListener,
if (mNeedsDrawableColorUpdate) {
mNeedsDrawableColorUpdate = false;
if (mKeyguardShowing) {
- mScrimInFront.setColors(mLockColors);
+ // Always animate color changes if we're seeing the keyguard
+ mScrimInFront.setColors(mLockColorsDark);
mScrimBehind.setColors(mLockColors);
} else {
- mScrimInFront.setColors(mSystemColors, true);
- mScrimBehind.setColors(mSystemColors, true);
+ // Only animate scrim color if the scrim view is actually visible
+ boolean animateScrimInFront = mScrimInFront.getViewAlpha() != 0;
+ boolean animateScrimBehind = mScrimBehind.getViewAlpha() != 0;
+ mScrimInFront.setColors(mSystemColorsDark, animateScrimInFront);
+ mScrimBehind.setColors(mSystemColors, animateScrimBehind);
}
}
@@ -647,14 +657,20 @@ public class ScrimController implements ViewTreeObserver.OnPreDrawListener,
}
@Override
- public void onColorsChanged(ColorExtractor.GradientColors colors, int which) {
+ public void onColorsChanged(ColorExtractor colorExtractor, int which) {
if ((which & WallpaperManager.FLAG_LOCK) != 0) {
- mLockColors = colors;
+ mLockColors = colorExtractor.getColors(WallpaperManager.FLAG_LOCK,
+ ColorExtractor.TYPE_NORMAL);
+ mLockColorsDark = colorExtractor.getColors(WallpaperManager.FLAG_LOCK,
+ ColorExtractor.TYPE_DARK);
mNeedsDrawableColorUpdate = true;
scheduleUpdate();
}
if ((which & WallpaperManager.FLAG_SYSTEM) != 0) {
- mSystemColors = colors;
+ mSystemColors = colorExtractor.getColors(WallpaperManager.FLAG_SYSTEM,
+ ColorExtractor.TYPE_NORMAL);
+ mSystemColorsDark = colorExtractor.getColors(WallpaperManager.FLAG_SYSTEM,
+ ColorExtractor.TYPE_DARK);
mNeedsDrawableColorUpdate = true;
scheduleUpdate();
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
index 30673cdfc086..3326b3f581d7 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
@@ -2805,7 +2805,7 @@ public class StatusBar extends SystemUI implements DemoMode,
}
@Override
- public void onColorsChanged(ColorExtractor.GradientColors colors, int which) {
+ public void onColorsChanged(ColorExtractor extractor, int which) {
updateTheme();
}
@@ -4477,6 +4477,8 @@ public class StatusBar extends SystemUI implements DemoMode,
*/
private void updateTheme() {
boolean useDarkTheme;
+ // Ignore visibility since we calculate the theme based on the real colors,
+ // not the current state.
if (mState == StatusBarState.KEYGUARD || mState == StatusBarState.SHADE_LOCKED) {
useDarkTheme = mColorExtractor.getColors(WallpaperManager.FLAG_LOCK)
.supportsDarkText();
diff --git a/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogImpl.java b/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogImpl.java
index 1d6bfb627801..1d3b533b6d8f 100644
--- a/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogImpl.java
@@ -1092,14 +1092,14 @@ public class VolumeDialogImpl implements VolumeDialog, TunerService.Tunable,
};
@Override
- public void onColorsChanged(ColorExtractor.GradientColors colors, int which) {
+ public void onColorsChanged(ColorExtractor extractor, int which) {
if (mKeyguard.isKeyguardLocked()) {
if ((WallpaperManager.FLAG_LOCK & which) != 0) {
- mGradientDrawable.setColors(colors);
+ mGradientDrawable.setColors(extractor.getColors(WallpaperManager.FLAG_LOCK));
}
} else {
if ((WallpaperManager.FLAG_SYSTEM & which) != 0) {
- mGradientDrawable.setColors(colors);
+ mGradientDrawable.setColors(extractor.getColors(WallpaperManager.FLAG_SYSTEM));
}
}
}
diff --git a/services/core/java/com/android/server/car/CarServiceHelperService.java b/services/core/java/com/android/server/car/CarServiceHelperService.java
new file mode 100644
index 000000000000..9392a6a8fcd9
--- /dev/null
+++ b/services/core/java/com/android/server/car/CarServiceHelperService.java
@@ -0,0 +1,91 @@
+/*
+ * Copyright (C) 2017 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.server.car;
+
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.content.ServiceConnection;
+import android.os.Binder;
+import android.os.IBinder;
+import android.os.Parcel;
+import android.os.RemoteException;
+import android.os.UserHandle;
+import android.util.Slog;
+
+import com.android.internal.car.ICarServiceHelper;
+import com.android.server.SystemService;
+
+/**
+ * System service side companion service for CarService.
+ * Starts car service and provide necessary API for CarService. Only for car product.
+ */
+public class CarServiceHelperService extends SystemService {
+ private static final String TAG = "CarServiceHelper";
+ private static final String CAR_SERVICE_INTERFACE = "android.car.ICar";
+ private final ICarServiceHelperImpl mHelper = new ICarServiceHelperImpl();
+ private IBinder mCarService;
+ private final ServiceConnection mCarServiceConnection = new ServiceConnection() {
+
+ @Override
+ public void onServiceConnected(ComponentName componentName, IBinder iBinder) {
+ Slog.i(TAG, "**CarService connected**");
+ mCarService = iBinder;
+ // Cannot depend on ICar which is defined in CarService, so handle binder call directly
+ // instead.
+ // void setCarServiceHelper(in IBinder helper)
+ Parcel data = Parcel.obtain();
+ data.writeInterfaceToken(CAR_SERVICE_INTERFACE);
+ data.writeStrongBinder(mHelper.asBinder());
+ try {
+ mCarService.transact(IBinder.FIRST_CALL_TRANSACTION, // setCarServiceHelper
+ data, null, Binder.FLAG_ONEWAY);
+ } catch (RemoteException e) {
+ Slog.w(TAG, "RemoteException from car service", e);
+ handleCarServiceCrash();
+ }
+ }
+
+ @Override
+ public void onServiceDisconnected(ComponentName componentName) {
+ handleCarServiceCrash();
+ }
+ };
+
+ public CarServiceHelperService(Context context) {
+ super(context);
+ }
+
+ @Override
+ public void onStart() {
+ Intent intent = new Intent();
+ intent.setPackage("com.android.car");
+ intent.setAction(CAR_SERVICE_INTERFACE);
+ if (!getContext().bindServiceAsUser(intent, mCarServiceConnection, Context.BIND_AUTO_CREATE,
+ UserHandle.SYSTEM)) {
+ Slog.wtf(TAG, "cannot start car service");
+ }
+ }
+
+ private void handleCarServiceCrash() {
+ //TODO define recovery bahavior
+ }
+
+ private class ICarServiceHelperImpl extends ICarServiceHelper.Stub {
+ //TODO
+ }
+}
diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java
index 66849c3e1348..272c11b985c5 100644
--- a/services/java/com/android/server/SystemServer.java
+++ b/services/java/com/android/server/SystemServer.java
@@ -63,6 +63,7 @@ import com.android.server.accessibility.AccessibilityManagerService;
import com.android.server.am.ActivityManagerService;
import com.android.server.audio.AudioService;
import com.android.server.camera.CameraServiceProxy;
+import com.android.server.car.CarServiceHelperService;
import com.android.server.clipboard.ClipboardService;
import com.android.server.connectivity.IpConnectivityMetrics;
import com.android.server.coverage.CoverageService;
@@ -1697,6 +1698,12 @@ public final class SystemServer {
}, WEBVIEW_PREPARATION);
}
+ if (mPackageManager.hasSystemFeature(PackageManager.FEATURE_AUTOMOTIVE)) {
+ traceBeginAndSlog("StartCarServiceHelperService");
+ mSystemServiceManager.startService(CarServiceHelperService.class);
+ traceEnd();
+ }
+
traceBeginAndSlog("StartSystemUI");
try {
startSystemUi(context, windowManagerF);
diff --git a/services/usb/java/com/android/server/usb/UsbDeviceManager.java b/services/usb/java/com/android/server/usb/UsbDeviceManager.java
index 415a59be25c7..42272fddb95b 100644
--- a/services/usb/java/com/android/server/usb/UsbDeviceManager.java
+++ b/services/usb/java/com/android/server/usb/UsbDeviceManager.java
@@ -1232,10 +1232,13 @@ public class UsbDeviceManager {
private String getDefaultFunctions() {
String func = SystemProperties.get(getPersistProp(true),
UsbManager.USB_FUNCTION_NONE);
- if (UsbManager.USB_FUNCTION_NONE.equals(func)) {
- func = UsbManager.USB_FUNCTION_MTP;
+ // if ADB is enabled, reset functions to ADB
+ // else enable MTP as usual.
+ if (UsbManager.containsFunction(func, UsbManager.USB_FUNCTION_ADB)) {
+ return UsbManager.USB_FUNCTION_ADB;
+ } else {
+ return UsbManager.USB_FUNCTION_MTP;
}
- return func;
}
public void dump(IndentingPrintWriter pw) {
diff --git a/telephony/java/android/telephony/CarrierConfigManager.java b/telephony/java/android/telephony/CarrierConfigManager.java
index 414780869a4d..9781fb16c2bb 100644
--- a/telephony/java/android/telephony/CarrierConfigManager.java
+++ b/telephony/java/android/telephony/CarrierConfigManager.java
@@ -1129,6 +1129,8 @@ public class CarrierConfigManager {
/** @hide */
public static final int CDMA_ROAMING_MODE_AFFILIATED = 1;
/** @hide */
+ public static final int IMSI_ENCRYPTION_DAYS_TIME_DISABLED = -1;
+ /** @hide */
public static final int CDMA_ROAMING_MODE_ANY = 2;
/**
* Boolean indicating if support is provided for directly dialing FDN number from FDN list.
@@ -1446,6 +1448,23 @@ public class CarrierConfigManager {
public static final String KEY_DISABLE_VOICE_BARRING_NOTIFICATION_BOOL =
"disable_voice_barring_notification_bool";
+ /**
+ * URL from which the proto containing the public key of the Carrier used for
+ * IMSI encryption will be downloaded.
+ * @hide
+ */
+ public static final String IMSI_KEY_DOWNLOAD_URL_STRING = "imsi_key_download_url_string";
+
+ /**
+ * Time in days, after which the key will expire, and a new key will need to be downloaded.
+ * default value is {@link IMSI_ENCRYPTION_DAYS_TIME_DISABLED}, and indicates that IMSI
+ * encryption is not enabled by default for a carrier. Value of 0 indicates that the key
+ * does not expire.
+ * @hide
+ */
+ public static final String IMSI_KEY_EXPIRATION_DAYS_TIME_INT =
+ "imsi_key_expiration_days_time_int";
+
/** The default value for every variable. */
private final static PersistableBundle sDefaults;
@@ -1693,6 +1712,8 @@ public class CarrierConfigManager {
sDefaults.putInt(KEY_LTE_EARFCNS_RSRP_BOOST_INT, 0);
sDefaults.putStringArray(KEY_BOOSTED_LTE_EARFCNS_STRING_ARRAY, null);
sDefaults.putBoolean(KEY_DISABLE_VOICE_BARRING_NOTIFICATION_BOOL, false);
+ sDefaults.putInt(IMSI_KEY_EXPIRATION_DAYS_TIME_INT, IMSI_ENCRYPTION_DAYS_TIME_DISABLED);
+ sDefaults.putString(IMSI_KEY_DOWNLOAD_URL_STRING, null);
}
/**