summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--api/current.txt4
-rw-r--r--api/system-current.txt4
-rw-r--r--api/test-current.txt4
-rwxr-xr-xcore/java/android/provider/Settings.java8
-rw-r--r--core/java/android/widget/AbsSeekBar.java5
-rw-r--r--core/java/android/widget/ProgressBar.java7
-rw-r--r--core/java/android/widget/TextView.java13
-rw-r--r--core/java/com/android/internal/app/NightDisplayController.java72
-rw-r--r--core/jni/android/graphics/Typeface.cpp19
-rw-r--r--core/res/res/values/config.xml10
-rw-r--r--core/res/res/values/symbols.xml3
-rw-r--r--graphics/java/android/graphics/Paint.java36
-rw-r--r--graphics/java/android/graphics/Typeface.java24
-rw-r--r--libs/hwui/SkiaCanvas.cpp39
-rw-r--r--libs/hwui/SkiaCanvasProxy.cpp17
-rw-r--r--libs/hwui/SkiaCanvasProxy.h5
-rw-r--r--libs/hwui/tests/unit/FatalTestCanvas.h4
-rw-r--r--packages/ExternalStorageProvider/AndroidManifest.xml1
-rw-r--r--packages/ExternalStorageProvider/res/values/strings.xml3
-rw-r--r--packages/PrintSpooler/src/com/android/printspooler/model/RemotePrintDocument.java41
-rw-r--r--packages/PrintSpooler/src/com/android/printspooler/ui/PrintActivity.java46
-rw-r--r--packages/PrintSpooler/src/com/android/printspooler/util/PageRangeUtils.java33
-rw-r--r--packages/SettingsLib/src/com/android/settingslib/applications/ApplicationsState.java6
-rw-r--r--services/core/java/com/android/server/LockSettingsService.java9
-rw-r--r--services/core/java/com/android/server/display/NightDisplayService.java178
-rw-r--r--services/core/java/com/android/server/net/NetworkStatsService.java1
-rw-r--r--services/usb/java/com/android/server/usb/UsbPortManager.java10
27 files changed, 426 insertions, 176 deletions
diff --git a/api/current.txt b/api/current.txt
index aab29be21d0f..6880c0ba18e6 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -13230,7 +13230,7 @@ package android.graphics {
method public void setFilterBitmap(boolean);
method public void setFlags(int);
method public void setFontFeatureSettings(java.lang.String);
- method public void setFontVariationSettings(java.lang.String);
+ method public boolean setFontVariationSettings(java.lang.String);
method public void setHinting(int);
method public void setLetterSpacing(float);
method public void setLinearText(boolean);
@@ -51263,7 +51263,7 @@ package android.widget {
method public void setExtractedText(android.view.inputmethod.ExtractedText);
method public void setFilters(android.text.InputFilter[]);
method public void setFontFeatureSettings(java.lang.String);
- method public void setFontVariationSettings(java.lang.String);
+ method public boolean setFontVariationSettings(java.lang.String);
method protected boolean setFrame(int, int, int, int);
method public void setFreezesText(boolean);
method public void setGravity(int);
diff --git a/api/system-current.txt b/api/system-current.txt
index 5e6717cbece4..3dac882e2d04 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -13965,7 +13965,7 @@ package android.graphics {
method public void setFilterBitmap(boolean);
method public void setFlags(int);
method public void setFontFeatureSettings(java.lang.String);
- method public void setFontVariationSettings(java.lang.String);
+ method public boolean setFontVariationSettings(java.lang.String);
method public void setHinting(int);
method public void setLetterSpacing(float);
method public void setLinearText(boolean);
@@ -55092,7 +55092,7 @@ package android.widget {
method public void setExtractedText(android.view.inputmethod.ExtractedText);
method public void setFilters(android.text.InputFilter[]);
method public void setFontFeatureSettings(java.lang.String);
- method public void setFontVariationSettings(java.lang.String);
+ method public boolean setFontVariationSettings(java.lang.String);
method protected boolean setFrame(int, int, int, int);
method public void setFreezesText(boolean);
method public void setGravity(int);
diff --git a/api/test-current.txt b/api/test-current.txt
index f91bbb9a045b..a891fde573b2 100644
--- a/api/test-current.txt
+++ b/api/test-current.txt
@@ -13268,7 +13268,7 @@ package android.graphics {
method public void setFilterBitmap(boolean);
method public void setFlags(int);
method public void setFontFeatureSettings(java.lang.String);
- method public void setFontVariationSettings(java.lang.String);
+ method public boolean setFontVariationSettings(java.lang.String);
method public void setHinting(int);
method public void setLetterSpacing(float);
method public void setLinearText(boolean);
@@ -51641,7 +51641,7 @@ package android.widget {
method public void setExtractedText(android.view.inputmethod.ExtractedText);
method public void setFilters(android.text.InputFilter[]);
method public void setFontFeatureSettings(java.lang.String);
- method public void setFontVariationSettings(java.lang.String);
+ method public boolean setFontVariationSettings(java.lang.String);
method protected boolean setFrame(int, int, int, int);
method public void setFreezesText(boolean);
method public void setGravity(int);
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index f0056c23259c..a35416fc17d9 100755
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -6788,6 +6788,13 @@ public final class Settings {
public static final String NIGHT_DISPLAY_AUTO_MODE = "night_display_auto_mode";
/**
+ * Control the color temperature of Night Display, represented in Kelvin.
+ * @hide
+ */
+ public static final String NIGHT_DISPLAY_COLOR_TEMPERATURE =
+ "night_display_color_temperature";
+
+ /**
* Custom time when Night display is scheduled to activate.
* Represented as milliseconds from midnight (e.g. 79200000 == 10pm).
* @hide
@@ -7022,6 +7029,7 @@ public final class Settings {
INCALL_POWER_BUTTON_BEHAVIOR,
NIGHT_DISPLAY_CUSTOM_START_TIME,
NIGHT_DISPLAY_CUSTOM_END_TIME,
+ NIGHT_DISPLAY_COLOR_TEMPERATURE,
NIGHT_DISPLAY_AUTO_MODE,
NIGHT_DISPLAY_ACTIVATED,
SYNC_PARENT_SOUNDS,
diff --git a/core/java/android/widget/AbsSeekBar.java b/core/java/android/widget/AbsSeekBar.java
index 5d136dca51ec..1d1fcc969b56 100644
--- a/core/java/android/widget/AbsSeekBar.java
+++ b/core/java/android/widget/AbsSeekBar.java
@@ -677,7 +677,6 @@ public abstract class AbsSeekBar extends ProgressBar {
protected synchronized void onDraw(Canvas canvas) {
super.onDraw(canvas);
drawThumb(canvas);
-
}
@Override
@@ -703,9 +702,9 @@ public abstract class AbsSeekBar extends ProgressBar {
}
/**
- * Draw the tick marks.
+ * @hide
*/
- void drawTickMarks(Canvas canvas) {
+ protected void drawTickMarks(Canvas canvas) {
if (mTickMark != null) {
final int count = getMax() - getMin();
if (count > 1) {
diff --git a/core/java/android/widget/ProgressBar.java b/core/java/android/widget/ProgressBar.java
index ec2adfbd6552..cabf8ea07094 100644
--- a/core/java/android/widget/ProgressBar.java
+++ b/core/java/android/widget/ProgressBar.java
@@ -851,6 +851,13 @@ public class ProgressBar extends View {
}
/**
+ * @hide
+ */
+ public boolean getMirrorForRtl() {
+ return mMirrorForRtl;
+ }
+
+ /**
* Applies the progress tints in order of increasing specificity.
*/
private void applyProgressTints() {
diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java
index 52e8ec8d1b86..f2a7f25decc1 100644
--- a/core/java/android/widget/TextView.java
+++ b/core/java/android/widget/TextView.java
@@ -3808,23 +3808,28 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
* @param fontVariationSettings font variation settings. You can pass null or empty string as
* no variation settings.
*
+ * @return true if the given settings is effective to at least one font file underlying this
+ * TextView. This function also returns true for empty settings string. Otherwise
+ * returns false.
+ *
* @see #getFontVariationSettings()
* @see Paint#getFontVariationSettings() Paint.getFontVariationSettings()
*/
- public void setFontVariationSettings(@Nullable String fontVariationSettings) {
+ public boolean setFontVariationSettings(@Nullable String fontVariationSettings) {
final String existingSettings = mTextPaint.getFontVariationSettings();
if (fontVariationSettings == existingSettings
|| (fontVariationSettings != null
&& fontVariationSettings.equals(existingSettings))) {
- return;
+ return true;
}
- mTextPaint.setFontVariationSettings(fontVariationSettings);
+ boolean effective = mTextPaint.setFontVariationSettings(fontVariationSettings);
- if (mLayout != null) {
+ if (effective && mLayout != null) {
nullLayouts();
requestLayout();
invalidate();
}
+ return effective;
}
/**
diff --git a/core/java/com/android/internal/app/NightDisplayController.java b/core/java/com/android/internal/app/NightDisplayController.java
index 68afe02be825..d19f1ecfbd13 100644
--- a/core/java/com/android/internal/app/NightDisplayController.java
+++ b/core/java/com/android/internal/app/NightDisplayController.java
@@ -46,7 +46,6 @@ public final class NightDisplayController {
private static final String TAG = "NightDisplayController";
private static final boolean DEBUG = false;
- /** @hide */
@Retention(RetentionPolicy.SOURCE)
@IntDef({ AUTO_MODE_DISABLED, AUTO_MODE_CUSTOM, AUTO_MODE_TWILIGHT })
public @interface AutoMode {}
@@ -233,6 +232,65 @@ public final class NightDisplayController {
Secure.NIGHT_DISPLAY_CUSTOM_END_TIME, endTime.toMillis(), mUserId);
}
+ /**
+ * Returns the color temperature (in Kelvin) to tint the display when activated.
+ */
+ public int getColorTemperature() {
+ int colorTemperature = Secure.getIntForUser(mContext.getContentResolver(),
+ Secure.NIGHT_DISPLAY_COLOR_TEMPERATURE, -1, mUserId);
+ if (colorTemperature == -1) {
+ if (DEBUG) {
+ Slog.d(TAG, "Using default value for setting: "
+ + Secure.NIGHT_DISPLAY_COLOR_TEMPERATURE);
+ }
+ colorTemperature = getDefaultColorTemperature();
+ }
+ final int minimumTemperature = getMinimumColorTemperature();
+ final int maximumTemperature = getMaximumColorTemperature();
+ if (colorTemperature < minimumTemperature) {
+ colorTemperature = minimumTemperature;
+ } else if (colorTemperature > maximumTemperature) {
+ colorTemperature = maximumTemperature;
+ }
+
+ return colorTemperature;
+ }
+
+ /**
+ * Sets the current temperature.
+ *
+ * @param colorTemperature the temperature, in Kelvin.
+ * @return {@code true} if new temperature was set successfully.
+ */
+ public boolean setColorTemperature(int colorTemperature) {
+ return Secure.putIntForUser(mContext.getContentResolver(),
+ Secure.NIGHT_DISPLAY_COLOR_TEMPERATURE, colorTemperature, mUserId);
+ }
+
+ /**
+ * Returns the minimum allowed color temperature (in Kelvin) to tint the display when activated.
+ */
+ public int getMinimumColorTemperature() {
+ return mContext.getResources().getInteger(
+ R.integer.config_nightDisplayColorTemperatureMin);
+ }
+
+ /**
+ * Returns the maximum allowed color temperature (in Kelvin) to tint the display when activated.
+ */
+ public int getMaximumColorTemperature() {
+ return mContext.getResources().getInteger(
+ R.integer.config_nightDisplayColorTemperatureMax);
+ }
+
+ /**
+ * Returns the default color temperature (in Kelvin) to tint the display when activated.
+ */
+ public int getDefaultColorTemperature() {
+ return mContext.getResources().getInteger(
+ R.integer.config_nightDisplayColorTemperatureDefault);
+ }
+
private void onSettingChanged(@NonNull String setting) {
if (DEBUG) {
Slog.d(TAG, "onSettingChanged: " + setting);
@@ -252,6 +310,9 @@ public final class NightDisplayController {
case Secure.NIGHT_DISPLAY_CUSTOM_END_TIME:
mCallback.onCustomEndTimeChanged(getCustomEndTime());
break;
+ case Secure.NIGHT_DISPLAY_COLOR_TEMPERATURE:
+ mCallback.onColorTemperatureChanged(getColorTemperature());
+ break;
}
}
}
@@ -278,6 +339,8 @@ public final class NightDisplayController {
false /* notifyForDescendants */, mContentObserver, mUserId);
cr.registerContentObserver(Secure.getUriFor(Secure.NIGHT_DISPLAY_CUSTOM_END_TIME),
false /* notifyForDescendants */, mContentObserver, mUserId);
+ cr.registerContentObserver(Secure.getUriFor(Secure.NIGHT_DISPLAY_COLOR_TEMPERATURE),
+ false /* notifyForDescendants */, mContentObserver, mUserId);
}
}
}
@@ -417,5 +480,12 @@ public final class NightDisplayController {
* @param endTime the local time to automatically deactivate Night display
*/
default void onCustomEndTimeChanged(LocalTime endTime) {}
+
+ /**
+ * Callback invoked when the color temperature changes.
+ *
+ * @param colorTemperature the color temperature to tint the screen
+ */
+ default void onColorTemperatureChanged(int colorTemperature) {}
}
}
diff --git a/core/jni/android/graphics/Typeface.cpp b/core/jni/android/graphics/Typeface.cpp
index 0cdc74fa92d8..d0b07d0168df 100644
--- a/core/jni/android/graphics/Typeface.cpp
+++ b/core/jni/android/graphics/Typeface.cpp
@@ -91,6 +91,24 @@ static void Typeface_setDefault(JNIEnv *env, jobject, jlong faceHandle) {
Typeface::setDefault(face);
}
+static jobject Typeface_getSupportedAxes(JNIEnv *env, jobject, jlong faceHandle) {
+ Typeface* face = reinterpret_cast<Typeface*>(faceHandle);
+ const std::unordered_set<minikin::AxisTag>& tagSet = face->fFontCollection->getSupportedTags();
+ const size_t length = tagSet.size();
+ if (length == 0) {
+ return nullptr;
+ }
+ std::vector<jint> tagVec(length);
+ int index = 0;
+ for (const auto& tag : tagSet) {
+ tagVec[index++] = tag;
+ }
+ std::sort(tagVec.begin(), tagVec.end());
+ const jintArray result = env->NewIntArray(length);
+ env->SetIntArrayRegion(result, 0, length, tagVec.data());
+ return result;
+}
+
///////////////////////////////////////////////////////////////////////////////
static const JNINativeMethod gTypefaceMethods[] = {
@@ -103,6 +121,7 @@ static const JNINativeMethod gTypefaceMethods[] = {
{ "nativeCreateFromArray", "([J)J",
(void*)Typeface_createFromArray },
{ "nativeSetDefault", "(J)V", (void*)Typeface_setDefault },
+ { "nativeGetSupportedAxes", "(J)[I", (void*)Typeface_getSupportedAxes },
};
int register_android_graphics_Typeface(JNIEnv* env)
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index 385f256f5d1c..c6cd7468e1ea 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -804,6 +804,16 @@
Represented as milliseconds from midnight (e.g. 21600000 == 6am). -->
<integer name="config_defaultNightDisplayCustomEndTime">21600000</integer>
+ <!-- Minimum color temperature, in Kelvin, supported by Night display. -->
+ <integer name="config_nightDisplayColorTemperatureMin">2596</integer>
+
+ <!-- Default color temperature, in Kelvin, to tint the screen when Night display is
+ activated. -->
+ <integer name="config_nightDisplayColorTemperatureDefault">2850</integer>
+
+ <!-- Maximum color temperature, in Kelvin, supported by Night display. -->
+ <integer name="config_nightDisplayColorTemperatureMax">4082</integer>
+
<!-- Indicate whether to allow the device to suspend when the screen is off
due to the proximity sensor. This resource should only be set to true
if the sensor HAL correctly handles the proximity sensor as a wake-up source.
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index 7201eaec0aaa..f6f29d9d3635 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -2767,6 +2767,9 @@
<java-symbol type="integer" name="config_defaultNightDisplayAutoMode" />
<java-symbol type="integer" name="config_defaultNightDisplayCustomStartTime" />
<java-symbol type="integer" name="config_defaultNightDisplayCustomEndTime" />
+ <java-symbol type="integer" name="config_nightDisplayColorTemperatureDefault" />
+ <java-symbol type="integer" name="config_nightDisplayColorTemperatureMin" />
+ <java-symbol type="integer" name="config_nightDisplayColorTemperatureMax" />
<!-- Default first user restrictions -->
<java-symbol type="array" name="config_defaultFirstUserRestrictions" />
diff --git a/graphics/java/android/graphics/Paint.java b/graphics/java/android/graphics/Paint.java
index 5d6aa8a5f16d..f4bf0798ad18 100644
--- a/graphics/java/android/graphics/Paint.java
+++ b/graphics/java/android/graphics/Paint.java
@@ -19,7 +19,9 @@ package android.graphics;
import android.annotation.ColorInt;
import android.annotation.NonNull;
import android.annotation.Size;
+import android.graphics.FontListParser;
import android.os.LocaleList;
+import android.text.FontConfig;
import android.text.GraphicsOperations;
import android.text.SpannableString;
import android.text.SpannedString;
@@ -30,6 +32,9 @@ import com.android.internal.annotations.GuardedBy;
import dalvik.annotation.optimization.CriticalNative;
import dalvik.annotation.optimization.FastNative;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
import java.util.HashMap;
import java.util.Locale;
@@ -1531,21 +1536,46 @@ public class Paint {
/**
* Set font variation settings.
*
+ * This function does nothing if none of the settings is applicable to underlying font files.
+ *
* @param settings font variation settings, e.g. "'wdth' 300, 'wght' 1.8"
*
* @see #getFontVariationSettings()
*
* @param settings the font variation settings. You can pass null or empty string as no
* variation settings.
+ * @return true if the given settings is effective to at least one font file underlying this
+ * typeface. This function also returns true for empty settings string. Otherwise
+ * returns false
*/
- public void setFontVariationSettings(String settings) {
+ public boolean setFontVariationSettings(String settings) {
settings = TextUtils.nullIfEmpty(settings);
if (settings == mFontVariationSettings
|| (settings != null && settings.equals(mFontVariationSettings))) {
- return;
+ return true;
+ }
+
+ if (settings == null || settings.length() == 0) {
+ mFontVariationSettings = null;
+ setTypeface(Typeface.createFromTypefaceWithVariation(mTypeface,
+ Collections.emptyList()));
+ return true;
+ }
+
+ final ArrayList<FontConfig.Axis> axes = FontListParser.parseFontVariationSettings(settings);
+ final ArrayList<FontConfig.Axis> filteredAxes = new ArrayList<FontConfig.Axis>();
+ for (int i = 0; i < axes.size(); ++i) {
+ final FontConfig.Axis axis = axes.get(i);
+ if (mTypeface.isSupportedAxes(axis.getTag())) {
+ filteredAxes.add(axis);
+ }
+ }
+ if (filteredAxes.isEmpty()) {
+ return false;
}
mFontVariationSettings = settings;
- setTypeface(Typeface.createFromTypefaceWithVariation(mTypeface, settings));
+ setTypeface(Typeface.createFromTypefaceWithVariation(mTypeface, filteredAxes));
+ return true;
}
/**
diff --git a/graphics/java/android/graphics/Typeface.java b/graphics/java/android/graphics/Typeface.java
index 341640146d02..8511c1f4dc94 100644
--- a/graphics/java/android/graphics/Typeface.java
+++ b/graphics/java/android/graphics/Typeface.java
@@ -53,6 +53,7 @@ import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;
+import java.util.Arrays;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
@@ -116,6 +117,9 @@ public class Typeface {
private int mStyle = 0;
+ private int[] mSupportedAxes;
+ private static final int[] EMPTY_AXES = {};
+
private static void setDefault(Typeface t) {
sDefaultTypeface = t;
nativeSetDefault(t.native_instance);
@@ -492,10 +496,8 @@ public class Typeface {
/** @hide */
public static Typeface createFromTypefaceWithVariation(Typeface family,
- String fontVariationSettings) {
+ List<FontConfig.Axis> axes) {
final long ni = family == null ? 0 : family.native_instance;
- ArrayList<FontConfig.Axis> axes =
- FontListParser.parseFontVariationSettings(fontVariationSettings);
return new Typeface(nativeCreateFromTypefaceWithVariation(ni, axes));
}
@@ -788,6 +790,21 @@ public class Typeface {
return result;
}
+ /** @hide */
+ public boolean isSupportedAxes(int axis) {
+ if (mSupportedAxes == null) {
+ synchronized (this) {
+ if (mSupportedAxes == null) {
+ mSupportedAxes = nativeGetSupportedAxes(native_instance);
+ if (mSupportedAxes == null) {
+ mSupportedAxes = EMPTY_AXES;
+ }
+ }
+ }
+ }
+ return Arrays.binarySearch(mSupportedAxes, axis) > 0;
+ }
+
private static native long nativeCreateFromTypeface(long native_instance, int style);
private static native long nativeCreateFromTypefaceWithVariation(
long native_instance, List<FontConfig.Axis> axes);
@@ -796,4 +813,5 @@ public class Typeface {
private static native int nativeGetStyle(long native_instance);
private static native long nativeCreateFromArray(long[] familyArray);
private static native void nativeSetDefault(long native_instance);
+ private static native int[] nativeGetSupportedAxes(long native_instance);
}
diff --git a/libs/hwui/SkiaCanvas.cpp b/libs/hwui/SkiaCanvas.cpp
index 812e4d885b39..daf14af87288 100644
--- a/libs/hwui/SkiaCanvas.cpp
+++ b/libs/hwui/SkiaCanvas.cpp
@@ -522,8 +522,10 @@ void SkiaCanvas::drawVertices(SkCanvas::VertexMode vertexMode, int vertexCount,
SkDEBUGFAIL("SkScalar must be a float for these conversions to be valid");
#endif
const int ptCount = vertexCount >> 1;
- mCanvas->drawVertices(vertexMode, ptCount, (SkPoint*)verts, (SkPoint*)texs,
- (SkColor*)colors, indices, indexCount, paint);
+ mCanvas->drawVertices(SkVertices::MakeCopy(vertexMode, ptCount, (SkPoint*)verts,
+ (SkPoint*)texs, (SkColor*)colors,
+ indexCount, indices),
+ SkBlendMode::kModulate, paint);
}
// ----------------------------------------------------------------------------
@@ -560,23 +562,17 @@ void SkiaCanvas::drawBitmapMesh(Bitmap& hwuiBitmap, int meshWidth, int meshHeigh
hwuiBitmap.getSkBitmap(&bitmap);
const int ptCount = (meshWidth + 1) * (meshHeight + 1);
const int indexCount = meshWidth * meshHeight * 6;
-
- /* Our temp storage holds 2 or 3 arrays.
- texture points [ptCount * sizeof(SkPoint)]
- optionally vertex points [ptCount * sizeof(SkPoint)] if we need a
- copy to convert from float to fixed
- indices [ptCount * sizeof(uint16_t)]
- */
- ssize_t storageSize = ptCount * sizeof(SkPoint); // texs[]
- storageSize += indexCount * sizeof(uint16_t); // indices[]
-
-
-#ifndef SK_SCALAR_IS_FLOAT
- SkDEBUGFAIL("SkScalar must be a float for these conversions to be valid");
-#endif
- std::unique_ptr<char[]> storage(new char[storageSize]);
- SkPoint* texs = (SkPoint*)storage.get();
- uint16_t* indices = (uint16_t*)(texs + ptCount);
+ uint32_t flags = SkVertices::kHasTexCoords_BuilderFlag;
+ if (colors) {
+ flags |= SkVertices::kHasColors_BuilderFlag;
+ }
+ SkVertices::Builder builder(SkCanvas::kTriangles_VertexMode, ptCount, indexCount, flags);
+ memcpy(builder.positions(), vertices, ptCount * sizeof(SkPoint));
+ if (colors) {
+ memcpy(builder.colors(), colors, ptCount * sizeof(SkColor));
+ }
+ SkPoint* texs = builder.texCoords();
+ uint16_t* indices = builder.indices();
// cons up texture coordinates and indices
{
@@ -625,7 +621,6 @@ void SkiaCanvas::drawBitmapMesh(Bitmap& hwuiBitmap, int meshWidth, int meshHeigh
index += 1;
}
SkASSERT(indexPtr - indices == indexCount);
- SkASSERT((char*)indexPtr - (char*)storage.get() == storageSize);
}
// double-check that we have legal indices
@@ -646,9 +641,7 @@ void SkiaCanvas::drawBitmapMesh(Bitmap& hwuiBitmap, int meshWidth, int meshHeigh
sk_sp<SkImage> image = SkMakeImageFromRasterBitmap(bitmap, kNever_SkCopyPixelsMode);
tmpPaint.setShader(image->makeShader(SkShader::kClamp_TileMode, SkShader::kClamp_TileMode));
- mCanvas->drawVertices(SkCanvas::kTriangles_VertexMode, ptCount, (SkPoint*)vertices,
- texs, (const SkColor*)colors, indices,
- indexCount, tmpPaint);
+ mCanvas->drawVertices(builder.detach(), SkBlendMode::kModulate, tmpPaint);
}
void SkiaCanvas::drawNinePatch(Bitmap& hwuiBitmap, const Res_png_9patch& chunk,
diff --git a/libs/hwui/SkiaCanvasProxy.cpp b/libs/hwui/SkiaCanvasProxy.cpp
index 20ca80b95465..f6e92dca2bb9 100644
--- a/libs/hwui/SkiaCanvasProxy.cpp
+++ b/libs/hwui/SkiaCanvasProxy.cpp
@@ -31,6 +31,7 @@
#include <SkRSXform.h>
#include <SkSurface.h>
#include <SkTextBlobRunIterator.h>
+#include <SkVertices.h>
namespace android {
namespace uirenderer {
@@ -180,20 +181,20 @@ void SkiaCanvasProxy::onDrawImageLattice(const SkImage* image, const Lattice& la
}
}
-void SkiaCanvasProxy::onDrawVertices(VertexMode mode, int vertexCount, const SkPoint vertices[],
- const SkPoint texs[], const SkColor colors[], SkBlendMode, const uint16_t indices[],
- int indexCount, const SkPaint& paint) {
+void SkiaCanvasProxy::onDrawVerticesObject(const SkVertices* vertices, SkBlendMode bmode,
+ const SkPaint& paint) {
// TODO: should we pass through blendmode
if (mFilterHwuiCalls) {
return;
}
// convert the SkPoints into floats
static_assert(sizeof(SkPoint) == sizeof(float)*2, "SkPoint is no longer two floats");
- const int floatCount = vertexCount << 1;
- const float* vArray = &vertices[0].fX;
- const float* tArray = (texs) ? &texs[0].fX : NULL;
- const int* cArray = (colors) ? (int*)colors : NULL;
- mCanvas->drawVertices(mode, floatCount, vArray, tArray, cArray, indices, indexCount, paint);
+ const int floatCount = vertices->vertexCount() << 1;
+ const float* vArray = (const float*)vertices->positions();
+ const float* tArray = (const float*)vertices->texCoords();
+ const int* cArray = (const int*)vertices->colors();
+ mCanvas->drawVertices(vertices->mode(), floatCount, vArray, tArray, cArray,
+ vertices->indices(), vertices->indexCount(), paint);
}
sk_sp<SkSurface> SkiaCanvasProxy::onNewSurface(const SkImageInfo&, const SkSurfaceProps&) {
diff --git a/libs/hwui/SkiaCanvasProxy.h b/libs/hwui/SkiaCanvasProxy.h
index 3b1dd7383f36..d11a779b3600 100644
--- a/libs/hwui/SkiaCanvasProxy.h
+++ b/libs/hwui/SkiaCanvasProxy.h
@@ -75,10 +75,7 @@ protected:
const SkPaint*);
virtual void onDrawImageLattice(const SkImage*, const Lattice& lattice, const SkRect& dst,
const SkPaint*);
- virtual void onDrawVertices(VertexMode, int vertexCount, const SkPoint vertices[],
- const SkPoint texs[], const SkColor colors[], SkBlendMode,
- const uint16_t indices[], int indexCount,
- const SkPaint&) override;
+ virtual void onDrawVerticesObject(const SkVertices*, SkBlendMode, const SkPaint&) override;
virtual void onDrawDRRect(const SkRRect&, const SkRRect&, const SkPaint&) override;
diff --git a/libs/hwui/tests/unit/FatalTestCanvas.h b/libs/hwui/tests/unit/FatalTestCanvas.h
index 4831722b93e6..03d94964ac76 100644
--- a/libs/hwui/tests/unit/FatalTestCanvas.h
+++ b/libs/hwui/tests/unit/FatalTestCanvas.h
@@ -80,9 +80,7 @@ public:
void onDrawPoints(PointMode, size_t count, const SkPoint pts[], const SkPaint&) {
ADD_FAILURE() << "onDrawPoints not expected in this test";
}
- void onDrawVertices(VertexMode, int vertexCount, const SkPoint vertices[], const SkPoint texs[],
- const SkColor colors[], SkBlendMode, const uint16_t indices[], int indexCount,
- const SkPaint&) {
+ void onDrawVerticesObject(const SkVertices*, SkBlendMode, const SkPaint&) {
ADD_FAILURE() << "onDrawVertices not expected in this test";
}
void onDrawAtlas(const SkImage*, const SkRSXform[], const SkRect[], const SkColor[], int count,
diff --git a/packages/ExternalStorageProvider/AndroidManifest.xml b/packages/ExternalStorageProvider/AndroidManifest.xml
index 0b290cebf053..1072f95371a0 100644
--- a/packages/ExternalStorageProvider/AndroidManifest.xml
+++ b/packages/ExternalStorageProvider/AndroidManifest.xml
@@ -9,6 +9,7 @@
<application android:label="@string/app_label">
<provider
android:name=".ExternalStorageProvider"
+ android:label="@string/storage_description"
android:authorities="com.android.externalstorage.documents"
android:grantUriPermissions="true"
android:exported="true"
diff --git a/packages/ExternalStorageProvider/res/values/strings.xml b/packages/ExternalStorageProvider/res/values/strings.xml
index 8b16d3c3b9d4..324fb59fe497 100644
--- a/packages/ExternalStorageProvider/res/values/strings.xml
+++ b/packages/ExternalStorageProvider/res/values/strings.xml
@@ -18,6 +18,9 @@
<!-- Title of the external storage application [CHAR LIMIT=32] -->
<string name="app_label">External Storage</string>
+ <!-- Meaningful storage location description shown to client applications [CHAR LIMIT=32] -->
+ <string name="storage_description">Local storage</string>
+
<!-- Title for documents backend that offers internal storage. [CHAR LIMIT=24] -->
<string name="root_internal_storage">Internal storage</string>
<!-- Title for directory in which a user may store their own documents and files. [CHAR LIMIT=24] -->
diff --git a/packages/PrintSpooler/src/com/android/printspooler/model/RemotePrintDocument.java b/packages/PrintSpooler/src/com/android/printspooler/model/RemotePrintDocument.java
index 6e1385a04f6b..187e35ac842c 100644
--- a/packages/PrintSpooler/src/com/android/printspooler/model/RemotePrintDocument.java
+++ b/packages/PrintSpooler/src/com/android/printspooler/model/RemotePrintDocument.java
@@ -94,10 +94,10 @@ public final class RemotePrintDocument {
// but the content has changed.
if (mNextCommand == null) {
if (mUpdateSpec.pages != null && (mDocumentInfo.changed
- || mDocumentInfo.writtenPages == null
+ || mDocumentInfo.pagesWrittenToFile == null
|| (mDocumentInfo.info.getPageCount()
!= PrintDocumentInfo.PAGE_COUNT_UNKNOWN
- && !PageRangeUtils.contains(mDocumentInfo.writtenPages,
+ && !PageRangeUtils.contains(mDocumentInfo.pagesWrittenToFile,
mUpdateSpec.pages, mDocumentInfo.info.getPageCount())))) {
mNextCommand = new WriteCommand(mContext, mLooper,
mPrintDocumentAdapter, mDocumentInfo,
@@ -106,9 +106,10 @@ public final class RemotePrintDocument {
} else {
if (mUpdateSpec.pages != null) {
// If we have the requested pages, update which ones to be printed.
- mDocumentInfo.printedPages = PageRangeUtils.computePrintedPages(
- mUpdateSpec.pages, mDocumentInfo.writtenPages,
- mDocumentInfo.info.getPageCount());
+ mDocumentInfo.pagesInFileToPrint =
+ PageRangeUtils.computeWhichPagesInFileToPrint(
+ mUpdateSpec.pages, mDocumentInfo.pagesWrittenToFile,
+ mDocumentInfo.info.getPageCount());
}
// Notify we are done.
mState = STATE_UPDATED;
@@ -514,8 +515,20 @@ public final class RemotePrintDocument {
public PrintAttributes attributes;
public Bundle metadata;
public PrintDocumentInfo info;
- public PageRange[] printedPages;
- public PageRange[] writtenPages;
+
+ /**
+ * Which pages out of the ones written to the file to print. This is not indexed by the
+ * document pages, but by the page number in the file.
+ * <p>E.g. if a document has 10 pages, we want pages 4-5 and 7, but only page 3-9 are in the
+ * file. This would contain 1-2 and 4.</p>
+ *
+ * @see PageRangeUtils#computeWhichPagesInFileToPrint
+ */
+ public PageRange[] pagesInFileToPrint;
+
+ /** Pages of the whole document that are currently written to file */
+ public PageRange[] pagesWrittenToFile;
+
public MutexFileProvider fileProvider;
public boolean changed;
public boolean updated;
@@ -783,8 +796,8 @@ public final class RemotePrintDocument {
if (changed || !equalsIgnoreSize(mDocument.info, info)) {
// If the content changed we throw away all pages as
// we will request them again with the new content.
- mDocument.writtenPages = null;
- mDocument.printedPages = null;
+ mDocument.pagesWrittenToFile = null;
+ mDocument.pagesInFileToPrint = null;
mDocument.changed = true;
}
@@ -1098,17 +1111,17 @@ public final class RemotePrintDocument {
}
PageRange[] writtenPages = PageRangeUtils.normalize(pages);
- PageRange[] printedPages = PageRangeUtils.computePrintedPages(
+ PageRange[] printedPages = PageRangeUtils.computeWhichPagesInFileToPrint(
mPages, writtenPages, mPageCount);
// Handle if we got invalid pages
if (printedPages != null) {
- mDocument.writtenPages = writtenPages;
- mDocument.printedPages = printedPages;
+ mDocument.pagesWrittenToFile = writtenPages;
+ mDocument.pagesInFileToPrint = printedPages;
completed();
} else {
- mDocument.writtenPages = null;
- mDocument.printedPages = null;
+ mDocument.pagesWrittenToFile = null;
+ mDocument.pagesInFileToPrint = null;
failed(mContext.getString(R.string.print_error_default_message));
}
diff --git a/packages/PrintSpooler/src/com/android/printspooler/ui/PrintActivity.java b/packages/PrintSpooler/src/com/android/printspooler/ui/PrintActivity.java
index 4b519171b3eb..f6df9953bf0f 100644
--- a/packages/PrintSpooler/src/com/android/printspooler/ui/PrintActivity.java
+++ b/packages/PrintSpooler/src/com/android/printspooler/ui/PrintActivity.java
@@ -85,8 +85,8 @@ import android.widget.EditText;
import android.widget.ImageView;
import android.widget.Spinner;
import android.widget.TextView;
-
import android.widget.Toast;
+
import com.android.internal.logging.MetricsLogger;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
import com.android.printspooler.R;
@@ -120,6 +120,7 @@ import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Objects;
+import java.util.function.Consumer;
public class PrintActivity extends Activity implements RemotePrintDocument.UpdateResultCallbacks,
PrintErrorFragment.OnActionListener, PageAdapter.ContentCallbacks,
@@ -543,8 +544,8 @@ public class PrintActivity extends Activity implements RemotePrintDocument.Updat
// pages in the printed document.
PrintDocumentInfo info = document.info;
if (info != null) {
- final int pageCount = PageRangeUtils.getNormalizedPageCount(document.writtenPages,
- getAdjustedPageCount(info));
+ final int pageCount = PageRangeUtils.getNormalizedPageCount(
+ document.pagesWrittenToFile, getAdjustedPageCount(info));
PrintDocumentInfo adjustedInfo = new PrintDocumentInfo.Builder(info.getName())
.setContentType(info.getContentType())
.setPageCount(pageCount)
@@ -558,7 +559,7 @@ public class PrintActivity extends Activity implements RemotePrintDocument.Updat
}
mPrintJob.setDocumentInfo(adjustedInfo);
- mPrintJob.setPages(document.printedPages);
+ mPrintJob.setPages(document.pagesInFileToPrint);
}
switch (mState) {
@@ -627,7 +628,7 @@ public class PrintActivity extends Activity implements RemotePrintDocument.Updat
// Update the preview controller.
mPrintPreviewController.onContentUpdated(contentUpdated,
getAdjustedPageCount(documentInfo.info),
- mPrintedDocument.getDocumentInfo().writtenPages,
+ mPrintedDocument.getDocumentInfo().pagesWrittenToFile,
mSelectedPages, mPrintJob.getAttributes().getMediaSize(),
mPrintJob.getAttributes().getMinMargins());
}
@@ -2105,14 +2106,15 @@ public class PrintActivity extends Activity implements RemotePrintDocument.Updat
// If saving to PDF, apply the attibutes as we are acting as a print service.
PrintAttributes attributes = mDestinationSpinnerAdapter.getPdfPrinter() == mCurrentPrinter
? mPrintJob.getAttributes() : null;
- new DocumentTransformer(this, mPrintJob, mFileProvider, attributes, new Runnable() {
- @Override
- public void run() {
+ new DocumentTransformer(this, mPrintJob, mFileProvider, attributes, error -> {
+ if (error == null) {
if (writeToUri != null) {
mPrintedDocument.writeContent(getContentResolver(), writeToUri);
}
setState(STATE_PRINT_COMPLETED);
doFinish();
+ } else {
+ onPrintDocumentError(error);
}
}).transform();
}
@@ -3096,11 +3098,11 @@ public class PrintActivity extends Activity implements RemotePrintDocument.Updat
private final PrintAttributes mAttributesToApply;
- private final Runnable mCallback;
+ private final Consumer<String> mCallback;
public DocumentTransformer(Context context, PrintJobInfo printJob,
MutexFileProvider fileProvider, PrintAttributes attributes,
- Runnable callback) {
+ Consumer<String> callback) {
mContext = context;
mPrintJob = printJob;
mFileProvider = fileProvider;
@@ -3112,7 +3114,7 @@ public class PrintActivity extends Activity implements RemotePrintDocument.Updat
public void transform() {
// If we have only the pages we want, done.
if (mPagesToShred.length <= 0 && mAttributesToApply == null) {
- mCallback.run();
+ mCallback.accept(null);
return;
}
@@ -3126,22 +3128,26 @@ public class PrintActivity extends Activity implements RemotePrintDocument.Updat
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
final IPdfEditor editor = IPdfEditor.Stub.asInterface(service);
- new AsyncTask<Void, Void, Void>() {
+ new AsyncTask<Void, Void, String>() {
@Override
- protected Void doInBackground(Void... params) {
+ protected String doInBackground(Void... params) {
// It's OK to access the data members as they are
// final and this code is the last one to touch
// them as shredding is the very last step, so the
// UI is not interactive at this point.
- doTransform(editor);
- updatePrintJob();
- return null;
+ try {
+ doTransform(editor);
+ updatePrintJob();
+ return null;
+ } catch (IOException | RemoteException | IllegalStateException e) {
+ return e.toString();
+ }
}
@Override
- protected void onPostExecute(Void aVoid) {
+ protected void onPostExecute(String error) {
mContext.unbindService(DocumentTransformer.this);
- mCallback.run();
+ mCallback.accept(error);
}
}.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
}
@@ -3151,7 +3157,7 @@ public class PrintActivity extends Activity implements RemotePrintDocument.Updat
/* do nothing */
}
- private void doTransform(IPdfEditor editor) {
+ private void doTransform(IPdfEditor editor) throws IOException, RemoteException {
File tempFile = null;
ParcelFileDescriptor src = null;
ParcelFileDescriptor dst = null;
@@ -3190,8 +3196,6 @@ public class PrintActivity extends Activity implements RemotePrintDocument.Updat
in = new FileInputStream(tempFile);
out = new FileOutputStream(jobFile);
Streams.copy(in, out);
- } catch (IOException|RemoteException e) {
- Log.e(LOG_TAG, "Error dropping pages", e);
} finally {
IoUtils.closeQuietly(src);
IoUtils.closeQuietly(dst);
diff --git a/packages/PrintSpooler/src/com/android/printspooler/util/PageRangeUtils.java b/packages/PrintSpooler/src/com/android/printspooler/util/PageRangeUtils.java
index 7425c033a7a4..a36f5837ecb1 100644
--- a/packages/PrintSpooler/src/com/android/printspooler/util/PageRangeUtils.java
+++ b/packages/PrintSpooler/src/com/android/printspooler/util/PageRangeUtils.java
@@ -394,33 +394,42 @@ public final class PageRangeUtils {
return pageRanges.getStart() == 0 && pageRanges.getEnd() == pageCount - 1;
}
- public static PageRange[] computePrintedPages(PageRange[] requestedPages,
- PageRange[] writtenPages, int pageCount) {
+ /**
+ * Compute the pages of the file that correspond to the requested pages in the doc.
+ *
+ * @param pagesInDocRequested The requested pages, doc-indexed
+ * @param pagesWrittenToFile The pages in the file
+ * @param pageCount The number of pages in the doc
+ *
+ * @return The pages, file-indexed
+ */
+ public static PageRange[] computeWhichPagesInFileToPrint(PageRange[] pagesInDocRequested,
+ PageRange[] pagesWrittenToFile, int pageCount) {
// Adjust the print job pages based on what was requested and written.
// The cases are ordered in the most expected to the least expected
// with a special case first where the app does not know the page count
// so we ask for all to be written.
- if (Arrays.equals(requestedPages, ALL_PAGES_RANGE)
+ if (Arrays.equals(pagesInDocRequested, ALL_PAGES_RANGE)
&& pageCount == PrintDocumentInfo.PAGE_COUNT_UNKNOWN) {
return ALL_PAGES_RANGE;
- } else if (Arrays.equals(writtenPages, requestedPages)) {
+ } else if (Arrays.equals(pagesWrittenToFile, pagesInDocRequested)) {
// We got a document with exactly the pages we wanted. Hence,
// the printer has to print all pages in the data.
return ALL_PAGES_RANGE;
- } else if (Arrays.equals(writtenPages, ALL_PAGES_RANGE)) {
+ } else if (Arrays.equals(pagesWrittenToFile, ALL_PAGES_RANGE)) {
// We requested specific pages but got all of them. Hence,
// the printer has to print only the requested pages.
- return requestedPages;
- } else if (PageRangeUtils.contains(writtenPages, requestedPages, pageCount)) {
+ return pagesInDocRequested;
+ } else if (PageRangeUtils.contains(pagesWrittenToFile, pagesInDocRequested, pageCount)) {
// We requested specific pages and got more but not all pages.
// Hence, we have to offset appropriately the printed pages to
// be based off the start of the written ones instead of zero.
// The written pages are always non-null and not empty.
- final int offset = -writtenPages[0].getStart();
- PageRangeUtils.offset(requestedPages, offset);
- return requestedPages;
- } else if (Arrays.equals(requestedPages, ALL_PAGES_RANGE)
- && isAllPages(writtenPages, pageCount)) {
+ final int offset = -pagesWrittenToFile[0].getStart();
+ PageRangeUtils.offset(pagesInDocRequested, offset);
+ return pagesInDocRequested;
+ } else if (Arrays.equals(pagesInDocRequested, ALL_PAGES_RANGE)
+ && isAllPages(pagesWrittenToFile, pageCount)) {
// We requested all pages via the special constant and got all
// of them as an explicit enumeration. Hence, the printer has
// to print only the requested pages.
diff --git a/packages/SettingsLib/src/com/android/settingslib/applications/ApplicationsState.java b/packages/SettingsLib/src/com/android/settingslib/applications/ApplicationsState.java
index 336942afcab7..c2ce7c9fd5de 100644
--- a/packages/SettingsLib/src/com/android/settingslib/applications/ApplicationsState.java
+++ b/packages/SettingsLib/src/com/android/settingslib/applications/ApplicationsState.java
@@ -686,7 +686,11 @@ public class ApplicationsState {
}
if (comparator != null) {
- Collections.sort(filteredApps, comparator);
+ synchronized (mEntriesMap) {
+ // Locking to ensure that the background handler does not mutate
+ // the size of AppEntries used for ordering while sorting.
+ Collections.sort(filteredApps, comparator);
+ }
}
synchronized (mRebuildSync) {
diff --git a/services/core/java/com/android/server/LockSettingsService.java b/services/core/java/com/android/server/LockSettingsService.java
index c946d0937017..2067620d83bf 100644
--- a/services/core/java/com/android/server/LockSettingsService.java
+++ b/services/core/java/com/android/server/LockSettingsService.java
@@ -146,7 +146,6 @@ public class LockSettingsService extends ILockSettings.Stub {
private final LockPatternUtils mLockPatternUtils;
private final NotificationManager mNotificationManager;
private final UserManager mUserManager;
- private final DevicePolicyManager mDevicePolicyManager;
private final IActivityManager mActivityManager;
private final KeyStore mKeyStore;
@@ -385,7 +384,6 @@ public class LockSettingsService extends ILockSettings.Stub {
mStorage = injector.getStorage();
mNotificationManager = injector.getNotificationManager();
mUserManager = injector.getUserManager();
- mDevicePolicyManager = injector.getDevicePolicyManager();
mStrongAuthTracker = injector.getStrongAuthTracker();
mStrongAuthTracker.register(mStrongAuth);
@@ -2214,20 +2212,21 @@ public class LockSettingsService extends ILockSettings.Stub {
Slog.i(TAG, "Managed profile can have escrow token");
return;
}
+ DevicePolicyManager dpm = mInjector.getDevicePolicyManager();
// Devices with Device Owner should have escrow enabled on all users.
- if (mDevicePolicyManager.getDeviceOwnerComponentOnAnyUser() != null) {
+ if (dpm.getDeviceOwnerComponentOnAnyUser() != null) {
Slog.i(TAG, "Corp-owned device can have escrow token");
return;
}
// We could also have a profile owner on the given (non-managed) user for unicorn cases
- if (mDevicePolicyManager.getProfileOwnerAsUser(userId) != null) {
+ if (dpm.getProfileOwnerAsUser(userId) != null) {
Slog.i(TAG, "User with profile owner can have escrow token");
return;
}
// If the device is yet to be provisioned (still in SUW), there is still
// a chance that Device Owner will be set on the device later, so postpone
// disabling escrow token for now.
- if (!mDevicePolicyManager.isDeviceProvisioned()) {
+ if (!dpm.isDeviceProvisioned()) {
Slog.i(TAG, "Postpone disabling escrow tokens until device is provisioned");
return;
}
diff --git a/services/core/java/com/android/server/display/NightDisplayService.java b/services/core/java/com/android/server/display/NightDisplayService.java
index cba694c866a2..d1275bb2224a 100644
--- a/services/core/java/com/android/server/display/NightDisplayService.java
+++ b/services/core/java/com/android/server/display/NightDisplayService.java
@@ -65,16 +65,6 @@ public final class NightDisplayService extends SystemService
private static final boolean DEBUG = false;
/**
- * Night display ~= 3400 K.
- */
- private static final float[] MATRIX_NIGHT = new float[] {
- 1, 0, 0, 0,
- 0, 0.754f, 0, 0,
- 0, 0, 0.516f, 0,
- 0, 0, 0, 1
- };
-
- /**
* The transition time, in milliseconds, for Night Display to turn on/off.
*/
private static final long TRANSITION_DURATION = 3000L;
@@ -112,13 +102,34 @@ public final class NightDisplayService extends SystemService
if (enabled) {
dtm.setColorMatrix(LEVEL_COLOR_MATRIX_NIGHT_DISPLAY, MATRIX_IDENTITY);
} else if (mController != null && mController.isActivated()) {
- dtm.setColorMatrix(LEVEL_COLOR_MATRIX_NIGHT_DISPLAY, MATRIX_NIGHT);
+ setMatrix(mController.getColorTemperature(), mMatrixNight);
+ dtm.setColorMatrix(LEVEL_COLOR_MATRIX_NIGHT_DISPLAY, mMatrixNight);
}
}
});
}
};
+ private float[] mMatrixNight = new float[16];
+
+ /**
+ * These coefficients were generated by an LLS quadratic regression fitted to the
+ * overdetermined system based on experimental readings (and subsequent conversion from xy
+ * chromaticity coordinates to gamma-corrected RGB values): { (temperature, R, G, B) } ->
+ * { (7304, 1.0, 1.0, 1.0), (4082, 1.0, 0.857, 0.719), (2850, 1.0, .754, .516),
+ * (2596, 1.0, 0.722, 0.454) }. The 3x3 matrix is formatted like so:
+ * <table>
+ * <tr><td>R: a coefficient</td><td>G: a coefficient</td><td>B: a coefficient</td></tr>
+ * <tr><td>R: b coefficient</td><td>G: b coefficient</td><td>B: b coefficient</td></tr>
+ * <tr><td>R: y-intercept</td><td>G: y-intercept</td><td>B: y-intercept</td></tr>
+ * </table>
+ */
+ private static final float[] mColorTempCoefficients = new float[] {
+ 0.0f, -0.00000000962353339f, -0.0000000189359041f,
+ 0.0f, 0.000153045476f, 0.000302412211f,
+ 1.0f, 0.390782778f, -0.198650895f
+ };
+
private int mCurrentUser = UserHandle.USER_NULL;
private ContentObserver mUserSetupObserver;
private boolean mBootCompleted;
@@ -232,6 +243,9 @@ public final class NightDisplayService extends SystemService
mController = new NightDisplayController(getContext(), mCurrentUser);
mController.setListener(this);
+ // Prepare color transformation matrix.
+ setMatrix(mController.getColorTemperature(), mMatrixNight);
+
// Initialize the current auto mode.
onAutoModeChanged(mController.getAutoMode());
@@ -239,6 +253,9 @@ public final class NightDisplayService extends SystemService
if (mIsActivated == null) {
onActivated(mController.isActivated());
}
+
+ // Transition the screen to the current temperature.
+ applyTint(false);
}
private void tearDown() {
@@ -273,53 +290,7 @@ public final class NightDisplayService extends SystemService
mIsActivated = activated;
- // Cancel the old animator if still running.
- if (mColorMatrixAnimator != null) {
- mColorMatrixAnimator.cancel();
- }
-
- // Don't do any color matrix change animations if we are ignoring them anyway.
- if (mIgnoreAllColorMatrixChanges.get()) {
- return;
- }
-
- final DisplayTransformManager dtm = getLocalService(DisplayTransformManager.class);
- final float[] from = dtm.getColorMatrix(LEVEL_COLOR_MATRIX_NIGHT_DISPLAY);
- final float[] to = mIsActivated ? MATRIX_NIGHT : null;
-
- mColorMatrixAnimator = ValueAnimator.ofObject(COLOR_MATRIX_EVALUATOR,
- from == null ? MATRIX_IDENTITY : from, to == null ? MATRIX_IDENTITY : to);
- mColorMatrixAnimator.setDuration(TRANSITION_DURATION);
- mColorMatrixAnimator.setInterpolator(AnimationUtils.loadInterpolator(
- getContext(), android.R.interpolator.fast_out_slow_in));
- mColorMatrixAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
- @Override
- public void onAnimationUpdate(ValueAnimator animator) {
- final float[] value = (float[]) animator.getAnimatedValue();
- dtm.setColorMatrix(LEVEL_COLOR_MATRIX_NIGHT_DISPLAY, value);
- }
- });
- mColorMatrixAnimator.addListener(new AnimatorListenerAdapter() {
-
- private boolean mIsCancelled;
-
- @Override
- public void onAnimationCancel(Animator animator) {
- mIsCancelled = true;
- }
-
- @Override
- public void onAnimationEnd(Animator animator) {
- if (!mIsCancelled) {
- // Ensure final color matrix is set at the end of the animation. If the
- // animation is cancelled then don't set the final color matrix so the new
- // animator can pick up from where this one left off.
- dtm.setColorMatrix(LEVEL_COLOR_MATRIX_NIGHT_DISPLAY, to);
- }
- mColorMatrixAnimator = null;
- }
- });
- mColorMatrixAnimator.start();
+ applyTint(false);
}
}
@@ -361,6 +332,97 @@ public final class NightDisplayService extends SystemService
}
}
+ @Override
+ public void onColorTemperatureChanged(int colorTemperature) {
+ setMatrix(colorTemperature, mMatrixNight);
+ applyTint(true);
+ }
+
+ /**
+ * Applies current color temperature matrix, or removes it if deactivated.
+ *
+ * @param immediate {@code true} skips transition animation
+ */
+ private void applyTint(boolean immediate) {
+ // Cancel the old animator if still running.
+ if (mColorMatrixAnimator != null) {
+ mColorMatrixAnimator.cancel();
+ }
+
+ // Don't do any color matrix change animations if we are ignoring them anyway.
+ if (mIgnoreAllColorMatrixChanges.get()) {
+ return;
+ }
+
+ final DisplayTransformManager dtm = getLocalService(DisplayTransformManager.class);
+ final float[] from = dtm.getColorMatrix(LEVEL_COLOR_MATRIX_NIGHT_DISPLAY);
+ final float[] to = mIsActivated ? mMatrixNight : MATRIX_IDENTITY;
+
+ if (immediate) {
+ dtm.setColorMatrix(LEVEL_COLOR_MATRIX_NIGHT_DISPLAY, to);
+ } else {
+ mColorMatrixAnimator = ValueAnimator.ofObject(COLOR_MATRIX_EVALUATOR,
+ from == null ? MATRIX_IDENTITY : from, to);
+ mColorMatrixAnimator.setDuration(TRANSITION_DURATION);
+ mColorMatrixAnimator.setInterpolator(AnimationUtils.loadInterpolator(
+ getContext(), android.R.interpolator.fast_out_slow_in));
+ mColorMatrixAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
+ @Override
+ public void onAnimationUpdate(ValueAnimator animator) {
+ final float[] value = (float[]) animator.getAnimatedValue();
+ dtm.setColorMatrix(LEVEL_COLOR_MATRIX_NIGHT_DISPLAY, value);
+ }
+ });
+ mColorMatrixAnimator.addListener(new AnimatorListenerAdapter() {
+
+ private boolean mIsCancelled;
+
+ @Override
+ public void onAnimationCancel(Animator animator) {
+ mIsCancelled = true;
+ }
+
+ @Override
+ public void onAnimationEnd(Animator animator) {
+ if (!mIsCancelled) {
+ // Ensure final color matrix is set at the end of the animation. If the
+ // animation is cancelled then don't set the final color matrix so the new
+ // animator can pick up from where this one left off.
+ dtm.setColorMatrix(LEVEL_COLOR_MATRIX_NIGHT_DISPLAY, to);
+ }
+ mColorMatrixAnimator = null;
+ }
+ });
+ mColorMatrixAnimator.start();
+ }
+ }
+
+ /**
+ * Set the color transformation {@code MATRIX_NIGHT} to the given color temperature.
+ *
+ * @param colorTemperature color temperature in Kelvin
+ * @param outTemp the 4x4 display transformation matrix for that color temperature
+ */
+ private void setMatrix(int colorTemperature, float[] outTemp) {
+ if (outTemp.length != 16) {
+ Slog.d(TAG, "The display transformation matrix must be 4x4");
+ return;
+ }
+
+ Matrix.setIdentityM(mMatrixNight, 0);
+
+ final float squareTemperature = colorTemperature * colorTemperature;
+ final float red = squareTemperature * mColorTempCoefficients[0]
+ + colorTemperature * mColorTempCoefficients[3] + mColorTempCoefficients[6];
+ final float green = squareTemperature * mColorTempCoefficients[1]
+ + colorTemperature * mColorTempCoefficients[4] + mColorTempCoefficients[7];
+ final float blue = squareTemperature * mColorTempCoefficients[2]
+ + colorTemperature * mColorTempCoefficients[5] + mColorTempCoefficients[8];
+ outTemp[0] = red;
+ outTemp[5] = green;
+ outTemp[10] = blue;
+ }
+
private abstract class AutoMode implements NightDisplayController.Callback {
public abstract void onStart();
public abstract void onStop();
diff --git a/services/core/java/com/android/server/net/NetworkStatsService.java b/services/core/java/com/android/server/net/NetworkStatsService.java
index 104c29619c96..6d666e890f9a 100644
--- a/services/core/java/com/android/server/net/NetworkStatsService.java
+++ b/services/core/java/com/android/server/net/NetworkStatsService.java
@@ -384,6 +384,7 @@ public class NetworkStatsService extends INetworkStatsService.Stub {
mContext.unregisterReceiver(mTetherReceiver);
mContext.unregisterReceiver(mPollReceiver);
mContext.unregisterReceiver(mRemovedReceiver);
+ mContext.unregisterReceiver(mUserReceiver);
mContext.unregisterReceiver(mShutdownReceiver);
final long currentTime = mTime.hasCache() ? mTime.currentTimeMillis()
diff --git a/services/usb/java/com/android/server/usb/UsbPortManager.java b/services/usb/java/com/android/server/usb/UsbPortManager.java
index 86f4a0168650..27297951cb6e 100644
--- a/services/usb/java/com/android/server/usb/UsbPortManager.java
+++ b/services/usb/java/com/android/server/usb/UsbPortManager.java
@@ -92,9 +92,6 @@ public class UsbPortManager {
// Cookie sent for usb hal death notification.
private static final int USB_HAL_DEATH_COOKIE = 1000;
- // Usb hal service name.
- private static String sServiceName = "usb_hal";
-
// Used as the key while sending the bundle to Main thread.
private static final String PORT_INFO = "port_info";
@@ -499,16 +496,15 @@ public class UsbPortManager {
}
try {
- mProxy = IUsb.getService(sServiceName);
+ mProxy = IUsb.getService();
mProxy.linkToDeath(new DeathRecipient(pw), USB_HAL_DEATH_COOKIE);
mProxy.setCallback(mHALCallback);
mProxy.queryPortStatus();
} catch (NoSuchElementException e) {
- logAndPrintException(pw, sServiceName + " not found."
+ logAndPrintException(pw, "connectToProxy: usb hal service not found."
+ " Did the service fail to start?", e);
} catch (RemoteException e) {
- logAndPrintException(pw, sServiceName
- + " connectToProxy: Service not responding", e);
+ logAndPrintException(pw, "connectToProxy: usb hal service not responding", e);
}
}
}