Merge changes I4a907600,If3205033
* changes:
Marking used instant apps fields as System API
Revert "Revert "Removes EphemrealResolverService and related""
diff --git a/Android.bp b/Android.bp
index 129d676..d5e04f9 100644
--- a/Android.bp
+++ b/Android.bp
@@ -676,6 +676,7 @@
"android.hardware.vibrator-V1.1-java-constants",
"android.hardware.wifi-V1.0-java-constants",
"android.hardware.radio-V1.0-java",
+ "android.hardware.usb.gadget-V1.0-java",
],
// Loaded with System.loadLibrary by android.view.textclassifier
diff --git a/Android.mk b/Android.mk
index 35b5f92..d72e398 100644
--- a/Android.mk
+++ b/Android.mk
@@ -821,6 +821,8 @@
LOCAL_SRC_FILES := \
$(call all-proto-files-under, core/proto) \
$(call all-proto-files-under, libs/incident/proto/android/os)
+# Protos have lots of MissingOverride and similar.
+LOCAL_ERROR_PRONE_FLAGS := -XepDisableAllChecks
include $(BUILD_STATIC_JAVA_LIBRARY)
# ==== hiddenapi lists =======================================
diff --git a/api/current.txt b/api/current.txt
index 7eafc9c..5a3bc1a 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -969,7 +969,9 @@
field public static final int orderingFromXml = 16843239; // 0x10101e7
field public static final int orientation = 16842948; // 0x10100c4
field public static final int outAnimation = 16843128; // 0x1010178
+ field public static final int outlineAmbientShadowColor = 16844162; // 0x1010582
field public static final int outlineProvider = 16843960; // 0x10104b8
+ field public static final int outlineSpotShadowColor = 16844161; // 0x1010581
field public static final int overScrollFooter = 16843459; // 0x10102c3
field public static final int overScrollHeader = 16843458; // 0x10102c2
field public static final int overScrollMode = 16843457; // 0x10102c1
@@ -6085,16 +6087,16 @@
method public android.os.ParcelFileDescriptor executeShellCommand(java.lang.String);
method public android.view.accessibility.AccessibilityNodeInfo findFocus(int);
method public android.view.accessibility.AccessibilityNodeInfo getRootInActiveWindow();
- method public final android.accessibilityservice.AccessibilityServiceInfo getServiceInfo();
+ method public android.accessibilityservice.AccessibilityServiceInfo getServiceInfo();
method public android.view.WindowAnimationFrameStats getWindowAnimationFrameStats();
method public android.view.WindowContentFrameStats getWindowContentFrameStats(int);
method public java.util.List<android.view.accessibility.AccessibilityWindowInfo> getWindows();
method public boolean injectInputEvent(android.view.InputEvent, boolean);
- method public final boolean performGlobalAction(int);
+ method public boolean performGlobalAction(int);
method public void setOnAccessibilityEventListener(android.app.UiAutomation.OnAccessibilityEventListener);
method public boolean setRotation(int);
method public void setRunAsMonkey(boolean);
- method public final void setServiceInfo(android.accessibilityservice.AccessibilityServiceInfo);
+ method public void setServiceInfo(android.accessibilityservice.AccessibilityServiceInfo);
method public android.graphics.Bitmap takeScreenshot();
method public void waitForIdle(long, long) throws java.util.concurrent.TimeoutException;
field public static final int FLAG_DONT_SUPPRESS_ACCESSIBILITY_SERVICES = 1; // 0x1
@@ -7250,6 +7252,7 @@
method public android.app.slice.Slice bindSlice(android.content.Intent, java.util.List<android.app.slice.SliceSpec>);
method public java.util.List<android.app.slice.SliceSpec> getPinnedSpecs(android.net.Uri);
method public java.util.Collection<android.net.Uri> getSliceDescendants(android.net.Uri);
+ method public android.net.Uri mapIntentToUri(android.content.Intent);
method public void pinSlice(android.net.Uri, java.util.List<android.app.slice.SliceSpec>);
method public deprecated void registerSliceCallback(android.net.Uri, android.app.slice.SliceManager.SliceCallback, java.util.List<android.app.slice.SliceSpec>);
method public deprecated void registerSliceCallback(android.net.Uri, android.app.slice.SliceManager.SliceCallback, java.util.List<android.app.slice.SliceSpec>, java.util.concurrent.Executor);
@@ -11629,15 +11632,9 @@
}
public final class AssetManager.AssetInputStream extends java.io.InputStream {
- method public final int available() throws java.io.IOException;
- method public final void close() throws java.io.IOException;
- method public final void mark(int);
- method public final boolean markSupported();
- method public final int read() throws java.io.IOException;
- method public final int read(byte[]) throws java.io.IOException;
- method public final int read(byte[], int, int) throws java.io.IOException;
- method public final void reset() throws java.io.IOException;
- method public final long skip(long) throws java.io.IOException;
+ method public void mark(int);
+ method public int read() throws java.io.IOException;
+ method public void reset() throws java.io.IOException;
}
public class ColorStateList implements android.os.Parcelable {
@@ -12399,7 +12396,7 @@
method public java.util.List<android.util.Pair<java.lang.String, java.lang.String>> getAttachedDbs();
method public long getMaximumSize();
method public long getPageSize();
- method public final java.lang.String getPath();
+ method public java.lang.String getPath();
method public deprecated java.util.Map<java.lang.String, java.lang.String> getSyncedTables();
method public int getVersion();
method public boolean inTransaction();
@@ -13056,29 +13053,29 @@
method public void eraseColor(int);
method public android.graphics.Bitmap extractAlpha();
method public android.graphics.Bitmap extractAlpha(android.graphics.Paint, int[]);
- method public final int getAllocationByteCount();
- method public final int getByteCount();
- method public final android.graphics.ColorSpace getColorSpace();
- method public final android.graphics.Bitmap.Config getConfig();
+ method public int getAllocationByteCount();
+ method public int getByteCount();
+ method public android.graphics.ColorSpace getColorSpace();
+ method public android.graphics.Bitmap.Config getConfig();
method public int getDensity();
method public int getGenerationId();
- method public final int getHeight();
+ method public int getHeight();
method public byte[] getNinePatchChunk();
method public int getPixel(int, int);
method public void getPixels(int[], int, int, int, int, int, int);
- method public final int getRowBytes();
+ method public int getRowBytes();
method public int getScaledHeight(android.graphics.Canvas);
method public int getScaledHeight(android.util.DisplayMetrics);
method public int getScaledHeight(int);
method public int getScaledWidth(android.graphics.Canvas);
method public int getScaledWidth(android.util.DisplayMetrics);
method public int getScaledWidth(int);
- method public final int getWidth();
- method public final boolean hasAlpha();
- method public final boolean hasMipMap();
- method public final boolean isMutable();
- method public final boolean isPremultiplied();
- method public final boolean isRecycled();
+ method public int getWidth();
+ method public boolean hasAlpha();
+ method public boolean hasMipMap();
+ method public boolean isMutable();
+ method public boolean isPremultiplied();
+ method public boolean isRecycled();
method public void prepareToDraw();
method public void reconfigure(int, int, android.graphics.Bitmap.Config);
method public void recycle();
@@ -13086,11 +13083,11 @@
method public void setConfig(android.graphics.Bitmap.Config);
method public void setDensity(int);
method public void setHasAlpha(boolean);
- method public final void setHasMipMap(boolean);
+ method public void setHasMipMap(boolean);
method public void setHeight(int);
method public void setPixel(int, int, int);
method public void setPixels(int[], int, int, int, int, int, int);
- method public final void setPremultiplied(boolean);
+ method public void setPremultiplied(boolean);
method public void setWidth(int);
method public void writeToParcel(android.os.Parcel, int);
field public static final android.os.Parcelable.Creator<android.graphics.Bitmap> CREATOR;
@@ -13162,7 +13159,7 @@
method public android.graphics.Bitmap decodeRegion(android.graphics.Rect, android.graphics.BitmapFactory.Options);
method public int getHeight();
method public int getWidth();
- method public final boolean isRecycled();
+ method public boolean isRecycled();
method public static android.graphics.BitmapRegionDecoder newInstance(byte[], int, int, boolean) throws java.io.IOException;
method public static android.graphics.BitmapRegionDecoder newInstance(java.io.FileDescriptor, boolean) throws java.io.IOException;
method public static android.graphics.BitmapRegionDecoder newInstance(java.io.InputStream, boolean) throws java.io.IOException;
@@ -14222,22 +14219,22 @@
ctor public Rect();
ctor public Rect(int, int, int, int);
ctor public Rect(android.graphics.Rect);
- method public final int centerX();
- method public final int centerY();
+ method public int centerX();
+ method public int centerY();
method public boolean contains(int, int);
method public boolean contains(int, int, int, int);
method public boolean contains(android.graphics.Rect);
method public int describeContents();
- method public final float exactCenterX();
- method public final float exactCenterY();
+ method public float exactCenterX();
+ method public float exactCenterY();
method public java.lang.String flattenToString();
- method public final int height();
+ method public int height();
method public void inset(int, int);
method public boolean intersect(int, int, int, int);
method public boolean intersect(android.graphics.Rect);
method public boolean intersects(int, int, int, int);
method public static boolean intersects(android.graphics.Rect, android.graphics.Rect);
- method public final boolean isEmpty();
+ method public boolean isEmpty();
method public void offset(int, int);
method public void offsetTo(int, int);
method public void readFromParcel(android.os.Parcel);
@@ -14251,7 +14248,7 @@
method public void union(int, int, int, int);
method public void union(android.graphics.Rect);
method public void union(int, int);
- method public final int width();
+ method public int width();
method public void writeToParcel(android.os.Parcel, int);
field public static final android.os.Parcelable.Creator<android.graphics.Rect> CREATOR;
field public int bottom;
@@ -15820,9 +15817,7 @@
}
public static final class CameraCharacteristics.Key<T> {
- method public final boolean equals(java.lang.Object);
method public java.lang.String getName();
- method public final int hashCode();
}
public abstract class CameraConstrainedHighSpeedCaptureSession extends android.hardware.camera2.CameraCaptureSession {
@@ -16184,9 +16179,7 @@
}
public static final class CaptureRequest.Key<T> {
- method public final boolean equals(java.lang.Object);
method public java.lang.String getName();
- method public final int hashCode();
}
public class CaptureResult extends android.hardware.camera2.CameraMetadata {
@@ -16279,9 +16272,7 @@
}
public static final class CaptureResult.Key<T> {
- method public final boolean equals(java.lang.Object);
method public java.lang.String getName();
- method public final int hashCode();
}
public final class DngCreator implements java.lang.AutoCloseable {
@@ -16393,7 +16384,7 @@
method public float getComponent(int);
method public float getGreenEven();
method public float getGreenOdd();
- method public final float getRed();
+ method public float getRed();
field public static final int BLUE = 3; // 0x3
field public static final int COUNT = 4; // 0x4
field public static final int GREEN_EVEN = 1; // 0x1
@@ -16421,16 +16412,16 @@
method public android.util.Range<java.lang.Integer>[] getHighSpeedVideoFpsRangesFor(android.util.Size);
method public android.util.Size[] getHighSpeedVideoSizes();
method public android.util.Size[] getHighSpeedVideoSizesFor(android.util.Range<java.lang.Integer>);
- method public final int[] getInputFormats();
+ method public int[] getInputFormats();
method public android.util.Size[] getInputSizes(int);
- method public final int[] getOutputFormats();
+ method public int[] getOutputFormats();
method public long getOutputMinFrameDuration(int, android.util.Size);
method public <T> long getOutputMinFrameDuration(java.lang.Class<T>, android.util.Size);
method public <T> android.util.Size[] getOutputSizes(java.lang.Class<T>);
method public android.util.Size[] getOutputSizes(int);
method public long getOutputStallDuration(int, android.util.Size);
method public <T> long getOutputStallDuration(java.lang.Class<T>, android.util.Size);
- method public final int[] getValidOutputFormatsForInput(int);
+ method public int[] getValidOutputFormatsForInput(int);
method public boolean isOutputSupportedFor(int);
method public static <T> boolean isOutputSupportedFor(java.lang.Class<T>);
method public boolean isOutputSupportedFor(android.view.Surface);
@@ -16738,12 +16729,12 @@
public final class UCharacter implements android.icu.lang.UCharacterEnums.ECharacterCategory android.icu.lang.UCharacterEnums.ECharacterDirection {
method public static int charCount(int);
- method public static final int codePointAt(java.lang.CharSequence, int);
- method public static final int codePointAt(char[], int);
- method public static final int codePointAt(char[], int, int);
- method public static final int codePointBefore(java.lang.CharSequence, int);
- method public static final int codePointBefore(char[], int);
- method public static final int codePointBefore(char[], int, int);
+ method public static int codePointAt(java.lang.CharSequence, int);
+ method public static int codePointAt(char[], int);
+ method public static int codePointAt(char[], int, int);
+ method public static int codePointBefore(java.lang.CharSequence, int);
+ method public static int codePointBefore(char[], int);
+ method public static int codePointBefore(char[], int, int);
method public static int codePointCount(java.lang.CharSequence, int, int);
method public static int codePointCount(char[], int, int);
method public static int digit(int, int);
@@ -16751,7 +16742,7 @@
method public static int foldCase(int, boolean);
method public static java.lang.String foldCase(java.lang.String, boolean);
method public static int foldCase(int, int);
- method public static final java.lang.String foldCase(java.lang.String, int);
+ method public static java.lang.String foldCase(java.lang.String, int);
method public static char forDigit(int, int);
method public static android.icu.util.VersionInfo getAge(int);
method public static int getBidiPairedBracket(int);
@@ -16803,8 +16794,8 @@
method public static boolean isPrintable(int);
method public static boolean isSpaceChar(int);
method public static boolean isSupplementary(int);
- method public static final boolean isSupplementaryCodePoint(int);
- method public static final boolean isSurrogatePair(char, char);
+ method public static boolean isSupplementaryCodePoint(int);
+ method public static boolean isSurrogatePair(char, char);
method public static boolean isTitleCase(int);
method public static boolean isUAlphabetic(int);
method public static boolean isULowercase(int);
@@ -16813,13 +16804,13 @@
method public static boolean isUnicodeIdentifierPart(int);
method public static boolean isUnicodeIdentifierStart(int);
method public static boolean isUpperCase(int);
- method public static final boolean isValidCodePoint(int);
+ method public static boolean isValidCodePoint(int);
method public static boolean isWhitespace(int);
method public static int offsetByCodePoints(java.lang.CharSequence, int, int);
method public static int offsetByCodePoints(char[], int, int, int, int);
- method public static final int toChars(int, char[], int);
- method public static final char[] toChars(int);
- method public static final int toCodePoint(char, char);
+ method public static int toChars(int, char[], int);
+ method public static char[] toChars(int);
+ method public static int toCodePoint(char, char);
method public static int toLowerCase(int);
method public static java.lang.String toLowerCase(java.lang.String);
method public static java.lang.String toLowerCase(java.util.Locale, java.lang.String);
@@ -17109,7 +17100,7 @@
}
public static final class UCharacter.UnicodeBlock extends java.lang.Character.Subset {
- method public static final android.icu.lang.UCharacter.UnicodeBlock forName(java.lang.String);
+ method public static android.icu.lang.UCharacter.UnicodeBlock forName(java.lang.String);
method public int getID();
method public static android.icu.lang.UCharacter.UnicodeBlock getInstance(int);
method public static android.icu.lang.UCharacter.UnicodeBlock of(int);
@@ -17916,20 +17907,20 @@
}
public final class UScript {
- method public static final boolean breaksBetweenLetters(int);
- method public static final int[] getCode(java.util.Locale);
- method public static final int[] getCode(android.icu.util.ULocale);
- method public static final int[] getCode(java.lang.String);
- method public static final int getCodeFromName(java.lang.String);
- method public static final java.lang.String getName(int);
- method public static final java.lang.String getSampleString(int);
- method public static final int getScript(int);
- method public static final int getScriptExtensions(int, java.util.BitSet);
- method public static final java.lang.String getShortName(int);
- method public static final android.icu.lang.UScript.ScriptUsage getUsage(int);
- method public static final boolean hasScript(int, int);
- method public static final boolean isCased(int);
- method public static final boolean isRightToLeft(int);
+ method public static boolean breaksBetweenLetters(int);
+ method public static int[] getCode(java.util.Locale);
+ method public static int[] getCode(android.icu.util.ULocale);
+ method public static int[] getCode(java.lang.String);
+ method public static int getCodeFromName(java.lang.String);
+ method public static java.lang.String getName(int);
+ method public static java.lang.String getSampleString(int);
+ method public static int getScript(int);
+ method public static int getScriptExtensions(int, java.util.BitSet);
+ method public static java.lang.String getShortName(int);
+ method public static android.icu.lang.UScript.ScriptUsage getUsage(int);
+ method public static boolean hasScript(int, int);
+ method public static boolean isCased(int);
+ method public static boolean isRightToLeft(int);
field public static final int ADLAM = 167; // 0xa7
field public static final int AFAKA = 147; // 0x93
field public static final int AHOM = 161; // 0xa1
@@ -18344,14 +18335,14 @@
method public deprecated int hashCode();
method public int next();
method public int previous();
- method public static final int primaryOrder(int);
+ method public static int primaryOrder(int);
method public void reset();
- method public static final int secondaryOrder(int);
+ method public static int secondaryOrder(int);
method public void setOffset(int);
method public void setText(java.lang.String);
method public void setText(android.icu.text.UCharacterIterator);
method public void setText(java.text.CharacterIterator);
- method public static final int tertiaryOrder(int);
+ method public static int tertiaryOrder(int);
field public static final int IGNORABLE = 0; // 0x0
field public static final int NULLORDER = -1; // 0xffffffff
}
@@ -19578,7 +19569,7 @@
method public boolean isUpperCaseFirst();
method public void setAlternateHandlingDefault();
method public void setAlternateHandlingShifted(boolean);
- method public final void setCaseFirstDefault();
+ method public void setCaseFirstDefault();
method public void setCaseLevel(boolean);
method public void setCaseLevelDefault();
method public void setDecompositionDefault();
@@ -20551,11 +20542,11 @@
public final class LocaleData {
method public static android.icu.util.VersionInfo getCLDRVersion();
method public java.lang.String getDelimiter(int);
- method public static final android.icu.util.LocaleData getInstance(android.icu.util.ULocale);
- method public static final android.icu.util.LocaleData getInstance();
- method public static final android.icu.util.LocaleData.MeasurementSystem getMeasurementSystem(android.icu.util.ULocale);
+ method public static android.icu.util.LocaleData getInstance(android.icu.util.ULocale);
+ method public static android.icu.util.LocaleData getInstance();
+ method public static android.icu.util.LocaleData.MeasurementSystem getMeasurementSystem(android.icu.util.ULocale);
method public boolean getNoSubstitute();
- method public static final android.icu.util.LocaleData.PaperSize getPaperSize(android.icu.util.ULocale);
+ method public static android.icu.util.LocaleData.PaperSize getPaperSize(android.icu.util.ULocale);
method public void setNoSubstitute(boolean);
field public static final int ALT_QUOTATION_END = 3; // 0x3
field public static final int ALT_QUOTATION_START = 2; // 0x2
@@ -21985,6 +21976,7 @@
method public java.util.List<android.media.AudioPlaybackConfiguration> getActivePlaybackConfigurations();
method public java.util.List<android.media.AudioRecordingConfiguration> getActiveRecordingConfigurations();
method public android.media.AudioDeviceInfo[] getDevices(int);
+ method public java.util.List<android.media.MicrophoneInfo> getMicrophones() throws java.io.IOException;
method public int getMode();
method public java.lang.String getParameters(java.lang.String);
method public java.lang.String getProperty(java.lang.String);
@@ -22163,6 +22155,7 @@
method public void addOnRoutingChangedListener(android.media.AudioRouting.OnRoutingChangedListener, android.os.Handler);
method public deprecated void addOnRoutingChangedListener(android.media.AudioRecord.OnRoutingChangedListener, android.os.Handler);
method protected void finalize();
+ method public java.util.List<android.media.MicrophoneInfo> getActiveMicrophones() throws java.io.IOException;
method public int getAudioFormat();
method public int getAudioSessionId();
method public int getAudioSource();
@@ -22827,40 +22820,40 @@
method public static android.media.MediaCodec createByCodecName(java.lang.String) throws java.io.IOException;
method public static android.media.MediaCodec createDecoderByType(java.lang.String) throws java.io.IOException;
method public static android.media.MediaCodec createEncoderByType(java.lang.String) throws java.io.IOException;
- method public final android.view.Surface createInputSurface();
+ method public android.view.Surface createInputSurface();
method public static android.view.Surface createPersistentInputSurface();
- method public final int dequeueInputBuffer(long);
- method public final int dequeueOutputBuffer(android.media.MediaCodec.BufferInfo, long);
+ method public int dequeueInputBuffer(long);
+ method public int dequeueOutputBuffer(android.media.MediaCodec.BufferInfo, long);
method protected void finalize();
- method public final void flush();
+ method public void flush();
method public android.media.MediaCodecInfo getCodecInfo();
method public java.nio.ByteBuffer getInputBuffer(int);
method public deprecated java.nio.ByteBuffer[] getInputBuffers();
- method public final android.media.MediaFormat getInputFormat();
+ method public android.media.MediaFormat getInputFormat();
method public android.media.Image getInputImage(int);
method public android.os.PersistableBundle getMetrics();
- method public final java.lang.String getName();
+ method public java.lang.String getName();
method public java.nio.ByteBuffer getOutputBuffer(int);
method public deprecated java.nio.ByteBuffer[] getOutputBuffers();
- method public final android.media.MediaFormat getOutputFormat();
- method public final android.media.MediaFormat getOutputFormat(int);
+ method public android.media.MediaFormat getOutputFormat();
+ method public android.media.MediaFormat getOutputFormat(int);
method public android.media.Image getOutputImage(int);
- method public final void queueInputBuffer(int, int, int, long, int) throws android.media.MediaCodec.CryptoException;
- method public final void queueSecureInputBuffer(int, int, android.media.MediaCodec.CryptoInfo, long, int) throws android.media.MediaCodec.CryptoException;
- method public final void release();
- method public final void releaseOutputBuffer(int, boolean);
- method public final void releaseOutputBuffer(int, long);
- method public final void reset();
+ method public void queueInputBuffer(int, int, int, long, int) throws android.media.MediaCodec.CryptoException;
+ method public void queueSecureInputBuffer(int, int, android.media.MediaCodec.CryptoInfo, long, int) throws android.media.MediaCodec.CryptoException;
+ method public void release();
+ method public void releaseOutputBuffer(int, boolean);
+ method public void releaseOutputBuffer(int, long);
+ method public void reset();
method public void setCallback(android.media.MediaCodec.Callback, android.os.Handler);
method public void setCallback(android.media.MediaCodec.Callback);
method public void setInputSurface(android.view.Surface);
method public void setOnFrameRenderedListener(android.media.MediaCodec.OnFrameRenderedListener, android.os.Handler);
method public void setOutputSurface(android.view.Surface);
- method public final void setParameters(android.os.Bundle);
- method public final void setVideoScalingMode(int);
- method public final void signalEndOfInputStream();
- method public final void start();
- method public final void stop();
+ method public void setParameters(android.os.Bundle);
+ method public void setVideoScalingMode(int);
+ method public void signalEndOfInputStream();
+ method public void start();
+ method public void stop();
field public static final int BUFFER_FLAG_CODEC_CONFIG = 2; // 0x2
field public static final int BUFFER_FLAG_END_OF_STREAM = 4; // 0x4
field public static final int BUFFER_FLAG_KEY_FRAME = 1; // 0x1
@@ -22954,10 +22947,10 @@
}
public final class MediaCodecInfo {
- method public final android.media.MediaCodecInfo.CodecCapabilities getCapabilitiesForType(java.lang.String);
- method public final java.lang.String getName();
- method public final java.lang.String[] getSupportedTypes();
- method public final boolean isEncoder();
+ method public android.media.MediaCodecInfo.CodecCapabilities getCapabilitiesForType(java.lang.String);
+ method public java.lang.String getName();
+ method public java.lang.String[] getSupportedTypes();
+ method public boolean isEncoder();
}
public static final class MediaCodecInfo.AudioCapabilities {
@@ -22977,9 +22970,9 @@
method public int getMaxSupportedInstances();
method public java.lang.String getMimeType();
method public android.media.MediaCodecInfo.VideoCapabilities getVideoCapabilities();
- method public final boolean isFeatureRequired(java.lang.String);
- method public final boolean isFeatureSupported(java.lang.String);
- method public final boolean isFormatSupported(android.media.MediaFormat);
+ method public boolean isFeatureRequired(java.lang.String);
+ method public boolean isFeatureSupported(java.lang.String);
+ method public boolean isFormatSupported(android.media.MediaFormat);
field public static final deprecated int COLOR_Format12bitRGB444 = 3; // 0x3
field public static final deprecated int COLOR_Format16bitARGB1555 = 5; // 0x5
field public static final deprecated int COLOR_Format16bitARGB4444 = 4; // 0x4
@@ -23237,11 +23230,11 @@
public final class MediaCodecList {
ctor public MediaCodecList(int);
- method public final java.lang.String findDecoderForFormat(android.media.MediaFormat);
- method public final java.lang.String findEncoderForFormat(android.media.MediaFormat);
- method public static final deprecated int getCodecCount();
- method public static final deprecated android.media.MediaCodecInfo getCodecInfoAt(int);
- method public final android.media.MediaCodecInfo[] getCodecInfos();
+ method public java.lang.String findDecoderForFormat(android.media.MediaFormat);
+ method public java.lang.String findEncoderForFormat(android.media.MediaFormat);
+ method public static deprecated int getCodecCount();
+ method public static deprecated android.media.MediaCodecInfo getCodecInfoAt(int);
+ method public android.media.MediaCodecInfo[] getCodecInfos();
field public static final int ALL_CODECS = 1; // 0x1
field public static final int REGULAR_CODECS = 0; // 0x0
}
@@ -23249,10 +23242,10 @@
public final class MediaCrypto {
ctor public MediaCrypto(java.util.UUID, byte[]) throws android.media.MediaCryptoException;
method protected void finalize();
- method public static final boolean isCryptoSchemeSupported(java.util.UUID);
- method public final void release();
- method public final boolean requiresSecureDecoderComponent(java.lang.String);
- method public final void setMediaDrmSession(byte[]) throws android.media.MediaCryptoException;
+ method public static boolean isCryptoSchemeSupported(java.util.UUID);
+ method public void release();
+ method public boolean requiresSecureDecoderComponent(java.lang.String);
+ method public void setMediaDrmSession(byte[]) throws android.media.MediaCryptoException;
}
public final class MediaCryptoException extends java.lang.Exception {
@@ -23268,10 +23261,10 @@
public final class MediaDescrambler implements java.lang.AutoCloseable {
ctor public MediaDescrambler(int) throws android.media.MediaCasException.UnsupportedCasException;
method public void close();
- method public final int descramble(java.nio.ByteBuffer, java.nio.ByteBuffer, android.media.MediaCodec.CryptoInfo);
+ method public int descramble(java.nio.ByteBuffer, java.nio.ByteBuffer, android.media.MediaCodec.CryptoInfo);
method protected void finalize();
- method public final boolean requiresSecureDecoderComponent(java.lang.String);
- method public final void setMediaCasSession(android.media.MediaCas.Session);
+ method public boolean requiresSecureDecoderComponent(java.lang.String);
+ method public void setMediaCasSession(android.media.MediaCas.Session);
}
public class MediaDescription implements android.os.Parcelable {
@@ -23327,8 +23320,8 @@
method public java.util.List<byte[]> getSecureStopIds();
method public java.util.List<byte[]> getSecureStops();
method public int getSecurityLevel(byte[]);
- method public static final boolean isCryptoSchemeSupported(java.util.UUID);
- method public static final boolean isCryptoSchemeSupported(java.util.UUID, java.lang.String);
+ method public static boolean isCryptoSchemeSupported(java.util.UUID);
+ method public static boolean isCryptoSchemeSupported(java.util.UUID, java.lang.String);
method public byte[] openSession() throws android.media.NotProvisionedException, android.media.ResourceBusyException;
method public byte[] provideKeyResponse(byte[], byte[]) throws android.media.DeniedByServerException, android.media.NotProvisionedException;
method public void provideProvisionResponse(byte[]) throws android.media.DeniedByServerException;
@@ -23489,21 +23482,21 @@
method public long getSampleSize();
method public long getSampleTime();
method public int getSampleTrackIndex();
- method public final int getTrackCount();
+ method public int getTrackCount();
method public android.media.MediaFormat getTrackFormat(int);
method public boolean hasCacheReachedEndOfStream();
method public int readSampleData(java.nio.ByteBuffer, int);
- method public final void release();
+ method public void release();
method public void seekTo(long, int);
method public void selectTrack(int);
- method public final void setDataSource(android.media.MediaDataSource) throws java.io.IOException;
- method public final void setDataSource(android.content.Context, android.net.Uri, java.util.Map<java.lang.String, java.lang.String>) throws java.io.IOException;
- method public final void setDataSource(java.lang.String, java.util.Map<java.lang.String, java.lang.String>) throws java.io.IOException;
- method public final void setDataSource(java.lang.String) throws java.io.IOException;
- method public final void setDataSource(android.content.res.AssetFileDescriptor) throws java.io.IOException, java.lang.IllegalArgumentException, java.lang.IllegalStateException;
- method public final void setDataSource(java.io.FileDescriptor) throws java.io.IOException;
- method public final void setDataSource(java.io.FileDescriptor, long, long) throws java.io.IOException;
- method public final void setMediaCas(android.media.MediaCas);
+ method public void setDataSource(android.media.MediaDataSource) throws java.io.IOException;
+ method public void setDataSource(android.content.Context, android.net.Uri, java.util.Map<java.lang.String, java.lang.String>) throws java.io.IOException;
+ method public void setDataSource(java.lang.String, java.util.Map<java.lang.String, java.lang.String>) throws java.io.IOException;
+ method public void setDataSource(java.lang.String) throws java.io.IOException;
+ method public void setDataSource(android.content.res.AssetFileDescriptor) throws java.io.IOException, java.lang.IllegalArgumentException, java.lang.IllegalStateException;
+ method public void setDataSource(java.io.FileDescriptor) throws java.io.IOException;
+ method public void setDataSource(java.io.FileDescriptor, long, long) throws java.io.IOException;
+ method public void setMediaCas(android.media.MediaCas);
method public void unselectTrack(int);
field public static final int SAMPLE_FLAG_ENCRYPTED = 2; // 0x2
field public static final int SAMPLE_FLAG_PARTIAL_FRAME = 4; // 0x4
@@ -23526,22 +23519,22 @@
public final class MediaFormat {
ctor public MediaFormat();
- method public final boolean containsKey(java.lang.String);
- method public static final android.media.MediaFormat createAudioFormat(java.lang.String, int, int);
- method public static final android.media.MediaFormat createSubtitleFormat(java.lang.String, java.lang.String);
- method public static final android.media.MediaFormat createVideoFormat(java.lang.String, int, int);
- method public final java.nio.ByteBuffer getByteBuffer(java.lang.String);
+ method public boolean containsKey(java.lang.String);
+ method public static android.media.MediaFormat createAudioFormat(java.lang.String, int, int);
+ method public static android.media.MediaFormat createSubtitleFormat(java.lang.String, java.lang.String);
+ method public static android.media.MediaFormat createVideoFormat(java.lang.String, int, int);
+ method public java.nio.ByteBuffer getByteBuffer(java.lang.String);
method public boolean getFeatureEnabled(java.lang.String);
- method public final float getFloat(java.lang.String);
- method public final int getInteger(java.lang.String);
- method public final long getLong(java.lang.String);
- method public final java.lang.String getString(java.lang.String);
- method public final void setByteBuffer(java.lang.String, java.nio.ByteBuffer);
+ method public float getFloat(java.lang.String);
+ method public int getInteger(java.lang.String);
+ method public long getLong(java.lang.String);
+ method public java.lang.String getString(java.lang.String);
+ method public void setByteBuffer(java.lang.String, java.nio.ByteBuffer);
method public void setFeatureEnabled(java.lang.String, boolean);
- method public final void setFloat(java.lang.String, float);
- method public final void setInteger(java.lang.String, int);
- method public final void setLong(java.lang.String, long);
- method public final void setString(java.lang.String, java.lang.String);
+ method public void setFloat(java.lang.String, float);
+ method public void setInteger(java.lang.String, int);
+ method public void setLong(java.lang.String, long);
+ method public void setString(java.lang.String, java.lang.String);
field public static final int COLOR_RANGE_FULL = 1; // 0x1
field public static final int COLOR_RANGE_LIMITED = 2; // 0x2
field public static final int COLOR_STANDARD_BT2020 = 6; // 0x6
@@ -24440,14 +24433,14 @@
public final class MediaSync {
ctor public MediaSync();
- method public final android.view.Surface createInputSurface();
+ method public android.view.Surface createInputSurface();
method protected void finalize();
method public void flush();
method public android.media.PlaybackParams getPlaybackParams();
method public android.media.SyncParams getSyncParams();
method public android.media.MediaTimestamp getTimestamp();
method public void queueAudio(java.nio.ByteBuffer, int, long);
- method public final void release();
+ method public void release();
method public void setAudioTrack(android.media.AudioTrack);
method public void setCallback(android.media.MediaSync.Callback, android.os.Handler);
method public void setOnErrorListener(android.media.MediaSync.OnErrorListener, android.os.Handler);
@@ -24482,6 +24475,41 @@
method public float getMediaClockRate();
}
+ public final class MicrophoneInfo {
+ method public java.util.List<android.util.Pair<java.lang.Integer, java.lang.Integer>> getChannelMapping();
+ method public java.lang.String getDescription();
+ method public int getDirectionality();
+ method public java.util.List<android.util.Pair<java.lang.Float, java.lang.Float>> getFrequencyResponse();
+ method public int getGroup();
+ method public int getId();
+ method public int getIndexInTheGroup();
+ method public int getLocation();
+ method public float getMaxSpl();
+ method public float getMinSpl();
+ method public android.media.MicrophoneInfo.Coordinate3F getOrientation();
+ method public android.media.MicrophoneInfo.Coordinate3F getPosition();
+ method public float getSensitivity();
+ method public int getType();
+ field public static final int CHANNEL_MAPPING_DIRECT = 1; // 0x1
+ field public static final int CHANNEL_MAPPING_PROCESSED = 2; // 0x2
+ field public static final int DIRECTIONALITY_BI_DIRECTIONAL = 2; // 0x2
+ field public static final int DIRECTIONALITY_CARDIOID = 3; // 0x3
+ field public static final int DIRECTIONALITY_HYPER_CARDIOID = 4; // 0x4
+ field public static final int DIRECTIONALITY_OMNI = 1; // 0x1
+ field public static final int DIRECTIONALITY_SUPER_CARDIOID = 5; // 0x5
+ field public static final int DIRECTIONALITY_UNKNOW = 0; // 0x0
+ field public static final int LOCATION_MAINBODY = 1; // 0x1
+ field public static final int LOCATION_MAINBODY_MOVABLE = 2; // 0x2
+ field public static final int LOCATION_PERIPHERAL = 3; // 0x3
+ field public static final int LOCATION_UNKNOWN = 0; // 0x0
+ }
+
+ public class MicrophoneInfo.Coordinate3F {
+ field public final float x;
+ field public final float y;
+ field public final float z;
+ }
+
public final class NotProvisionedException extends android.media.MediaDrmException {
ctor public NotProvisionedException(java.lang.String);
}
@@ -25402,7 +25430,7 @@
public final class MidiInputPort extends android.media.midi.MidiReceiver implements java.io.Closeable {
method public void close() throws java.io.IOException;
- method public final int getPortNumber();
+ method public int getPortNumber();
method public void onSend(byte[], int, int, long) throws java.io.IOException;
}
@@ -25427,7 +25455,7 @@
public final class MidiOutputPort extends android.media.midi.MidiSender implements java.io.Closeable {
method public void close() throws java.io.IOException;
- method public final int getPortNumber();
+ method public int getPortNumber();
method public void onConnect(android.media.midi.MidiReceiver);
method public void onDisconnect(android.media.midi.MidiReceiver);
}
@@ -25702,7 +25730,7 @@
package android.media.tv {
public final class TvContentRating {
- method public final boolean contains(android.media.tv.TvContentRating);
+ method public boolean contains(android.media.tv.TvContentRating);
method public static android.media.tv.TvContentRating createRating(java.lang.String, java.lang.String, java.lang.String, java.lang.String...);
method public java.lang.String flattenToString();
method public java.lang.String getDomain();
@@ -25752,7 +25780,7 @@
}
public static final class TvContract.Channels implements android.media.tv.TvContract.BaseTvColumns {
- method public static final java.lang.String getVideoResolution(java.lang.String);
+ method public static java.lang.String getVideoResolution(java.lang.String);
field public static final java.lang.String COLUMN_APP_LINK_COLOR = "app_link_color";
field public static final java.lang.String COLUMN_APP_LINK_ICON_URI = "app_link_icon_uri";
field public static final java.lang.String COLUMN_APP_LINK_INTENT_URI = "app_link_intent_uri";
@@ -26277,18 +26305,18 @@
public final class TvTrackInfo implements android.os.Parcelable {
method public int describeContents();
- method public final int getAudioChannelCount();
- method public final int getAudioSampleRate();
- method public final java.lang.CharSequence getDescription();
- method public final android.os.Bundle getExtra();
- method public final java.lang.String getId();
- method public final java.lang.String getLanguage();
- method public final int getType();
- method public final byte getVideoActiveFormatDescription();
- method public final float getVideoFrameRate();
- method public final int getVideoHeight();
- method public final float getVideoPixelAspectRatio();
- method public final int getVideoWidth();
+ method public int getAudioChannelCount();
+ method public int getAudioSampleRate();
+ method public java.lang.CharSequence getDescription();
+ method public android.os.Bundle getExtra();
+ method public java.lang.String getId();
+ method public java.lang.String getLanguage();
+ method public int getType();
+ method public byte getVideoActiveFormatDescription();
+ method public float getVideoFrameRate();
+ method public int getVideoHeight();
+ method public float getVideoPixelAspectRatio();
+ method public int getVideoWidth();
method public void writeToParcel(android.os.Parcel, int);
field public static final android.os.Parcelable.Creator<android.media.tv.TvTrackInfo> CREATOR;
field public static final int TYPE_AUDIO = 0; // 0x0
@@ -26299,16 +26327,16 @@
public static final class TvTrackInfo.Builder {
ctor public TvTrackInfo.Builder(int, java.lang.String);
method public android.media.tv.TvTrackInfo build();
- method public final android.media.tv.TvTrackInfo.Builder setAudioChannelCount(int);
- method public final android.media.tv.TvTrackInfo.Builder setAudioSampleRate(int);
- method public final android.media.tv.TvTrackInfo.Builder setDescription(java.lang.CharSequence);
- method public final android.media.tv.TvTrackInfo.Builder setExtra(android.os.Bundle);
- method public final android.media.tv.TvTrackInfo.Builder setLanguage(java.lang.String);
- method public final android.media.tv.TvTrackInfo.Builder setVideoActiveFormatDescription(byte);
- method public final android.media.tv.TvTrackInfo.Builder setVideoFrameRate(float);
- method public final android.media.tv.TvTrackInfo.Builder setVideoHeight(int);
- method public final android.media.tv.TvTrackInfo.Builder setVideoPixelAspectRatio(float);
- method public final android.media.tv.TvTrackInfo.Builder setVideoWidth(int);
+ method public android.media.tv.TvTrackInfo.Builder setAudioChannelCount(int);
+ method public android.media.tv.TvTrackInfo.Builder setAudioSampleRate(int);
+ method public android.media.tv.TvTrackInfo.Builder setDescription(java.lang.CharSequence);
+ method public android.media.tv.TvTrackInfo.Builder setExtra(android.os.Bundle);
+ method public android.media.tv.TvTrackInfo.Builder setLanguage(java.lang.String);
+ method public android.media.tv.TvTrackInfo.Builder setVideoActiveFormatDescription(byte);
+ method public android.media.tv.TvTrackInfo.Builder setVideoFrameRate(float);
+ method public android.media.tv.TvTrackInfo.Builder setVideoHeight(int);
+ method public android.media.tv.TvTrackInfo.Builder setVideoPixelAspectRatio(float);
+ method public android.media.tv.TvTrackInfo.Builder setVideoWidth(int);
}
public class TvView extends android.view.ViewGroup {
@@ -26539,34 +26567,34 @@
}
public final class MtpObjectInfo {
- method public final int getAssociationDesc();
- method public final int getAssociationType();
- method public final int getCompressedSize();
- method public final long getCompressedSizeLong();
- method public final long getDateCreated();
- method public final long getDateModified();
- method public final int getFormat();
- method public final int getImagePixDepth();
- method public final long getImagePixDepthLong();
- method public final int getImagePixHeight();
- method public final long getImagePixHeightLong();
- method public final int getImagePixWidth();
- method public final long getImagePixWidthLong();
- method public final java.lang.String getKeywords();
- method public final java.lang.String getName();
- method public final int getObjectHandle();
- method public final int getParent();
- method public final int getProtectionStatus();
- method public final int getSequenceNumber();
- method public final long getSequenceNumberLong();
- method public final int getStorageId();
- method public final int getThumbCompressedSize();
- method public final long getThumbCompressedSizeLong();
- method public final int getThumbFormat();
- method public final int getThumbPixHeight();
- method public final long getThumbPixHeightLong();
- method public final int getThumbPixWidth();
- method public final long getThumbPixWidthLong();
+ method public int getAssociationDesc();
+ method public int getAssociationType();
+ method public int getCompressedSize();
+ method public long getCompressedSizeLong();
+ method public long getDateCreated();
+ method public long getDateModified();
+ method public int getFormat();
+ method public int getImagePixDepth();
+ method public long getImagePixDepthLong();
+ method public int getImagePixHeight();
+ method public long getImagePixHeightLong();
+ method public int getImagePixWidth();
+ method public long getImagePixWidthLong();
+ method public java.lang.String getKeywords();
+ method public java.lang.String getName();
+ method public int getObjectHandle();
+ method public int getParent();
+ method public int getProtectionStatus();
+ method public int getSequenceNumber();
+ method public long getSequenceNumberLong();
+ method public int getStorageId();
+ method public int getThumbCompressedSize();
+ method public long getThumbCompressedSizeLong();
+ method public int getThumbFormat();
+ method public int getThumbPixHeight();
+ method public long getThumbPixHeightLong();
+ method public int getThumbPixWidth();
+ method public long getThumbPixWidthLong();
}
public static class MtpObjectInfo.Builder {
@@ -26596,11 +26624,11 @@
}
public final class MtpStorageInfo {
- method public final java.lang.String getDescription();
- method public final long getFreeSpace();
- method public final long getMaxCapacity();
- method public final int getStorageId();
- method public final java.lang.String getVolumeIdentifier();
+ method public java.lang.String getDescription();
+ method public long getFreeSpace();
+ method public long getMaxCapacity();
+ method public int getStorageId();
+ method public java.lang.String getVolumeIdentifier();
}
}
@@ -27033,10 +27061,10 @@
public final class Proxy {
ctor public Proxy();
- method public static final deprecated java.lang.String getDefaultHost();
- method public static final deprecated int getDefaultPort();
- method public static final deprecated java.lang.String getHost(android.content.Context);
- method public static final deprecated int getPort(android.content.Context);
+ method public static deprecated java.lang.String getDefaultHost();
+ method public static deprecated int getDefaultPort();
+ method public static deprecated java.lang.String getHost(android.content.Context);
+ method public static deprecated int getPort(android.content.Context);
field public static final deprecated java.lang.String EXTRA_PROXY_INFO = "android.intent.extra.PROXY_INFO";
field public static final java.lang.String PROXY_CHANGE_ACTION = "android.intent.action.PROXY_CHANGE";
}
@@ -32063,9 +32091,9 @@
method public static void dumpHprofData(java.lang.String) throws java.io.IOException;
method public static boolean dumpService(java.lang.String, java.io.FileDescriptor, java.lang.String[]);
method public static void enableEmulatorTraceOutput();
- method public static final int getBinderDeathObjectCount();
- method public static final int getBinderLocalObjectCount();
- method public static final int getBinderProxyObjectCount();
+ method public static int getBinderDeathObjectCount();
+ method public static int getBinderLocalObjectCount();
+ method public static int getBinderProxyObjectCount();
method public static int getBinderReceivedTransactions();
method public static int getBinderSentTransactions();
method public static deprecated int getGlobalAllocCount();
@@ -32474,114 +32502,114 @@
}
public final class Parcel {
- method public final void appendFrom(android.os.Parcel, int, int);
- method public final android.os.IBinder[] createBinderArray();
- method public final java.util.ArrayList<android.os.IBinder> createBinderArrayList();
- method public final boolean[] createBooleanArray();
- method public final byte[] createByteArray();
- method public final char[] createCharArray();
- method public final double[] createDoubleArray();
- method public final float[] createFloatArray();
- method public final int[] createIntArray();
- method public final long[] createLongArray();
- method public final java.lang.String[] createStringArray();
- method public final java.util.ArrayList<java.lang.String> createStringArrayList();
- method public final <T> T[] createTypedArray(android.os.Parcelable.Creator<T>);
- method public final <T> java.util.ArrayList<T> createTypedArrayList(android.os.Parcelable.Creator<T>);
- method public final int dataAvail();
- method public final int dataCapacity();
- method public final int dataPosition();
- method public final int dataSize();
- method public final void enforceInterface(java.lang.String);
- method public final boolean hasFileDescriptors();
- method public final byte[] marshall();
+ method public void appendFrom(android.os.Parcel, int, int);
+ method public android.os.IBinder[] createBinderArray();
+ method public java.util.ArrayList<android.os.IBinder> createBinderArrayList();
+ method public boolean[] createBooleanArray();
+ method public byte[] createByteArray();
+ method public char[] createCharArray();
+ method public double[] createDoubleArray();
+ method public float[] createFloatArray();
+ method public int[] createIntArray();
+ method public long[] createLongArray();
+ method public java.lang.String[] createStringArray();
+ method public java.util.ArrayList<java.lang.String> createStringArrayList();
+ method public <T> T[] createTypedArray(android.os.Parcelable.Creator<T>);
+ method public <T> java.util.ArrayList<T> createTypedArrayList(android.os.Parcelable.Creator<T>);
+ method public int dataAvail();
+ method public int dataCapacity();
+ method public int dataPosition();
+ method public int dataSize();
+ method public void enforceInterface(java.lang.String);
+ method public boolean hasFileDescriptors();
+ method public byte[] marshall();
method public static android.os.Parcel obtain();
- method public final java.lang.Object[] readArray(java.lang.ClassLoader);
- method public final java.util.ArrayList readArrayList(java.lang.ClassLoader);
- method public final void readBinderArray(android.os.IBinder[]);
- method public final void readBinderList(java.util.List<android.os.IBinder>);
- method public final void readBooleanArray(boolean[]);
- method public final android.os.Bundle readBundle();
- method public final android.os.Bundle readBundle(java.lang.ClassLoader);
- method public final byte readByte();
- method public final void readByteArray(byte[]);
- method public final void readCharArray(char[]);
- method public final double readDouble();
- method public final void readDoubleArray(double[]);
- method public final void readException();
- method public final void readException(int, java.lang.String);
- method public final android.os.ParcelFileDescriptor readFileDescriptor();
- method public final float readFloat();
- method public final void readFloatArray(float[]);
- method public final java.util.HashMap readHashMap(java.lang.ClassLoader);
- method public final int readInt();
- method public final void readIntArray(int[]);
- method public final void readList(java.util.List, java.lang.ClassLoader);
- method public final long readLong();
- method public final void readLongArray(long[]);
- method public final void readMap(java.util.Map, java.lang.ClassLoader);
- method public final <T extends android.os.Parcelable> T readParcelable(java.lang.ClassLoader);
- method public final android.os.Parcelable[] readParcelableArray(java.lang.ClassLoader);
- method public final android.os.PersistableBundle readPersistableBundle();
- method public final android.os.PersistableBundle readPersistableBundle(java.lang.ClassLoader);
- method public final java.io.Serializable readSerializable();
- method public final android.util.Size readSize();
- method public final android.util.SizeF readSizeF();
- method public final android.util.SparseArray readSparseArray(java.lang.ClassLoader);
- method public final android.util.SparseBooleanArray readSparseBooleanArray();
- method public final java.lang.String readString();
- method public final void readStringArray(java.lang.String[]);
- method public final void readStringList(java.util.List<java.lang.String>);
- method public final android.os.IBinder readStrongBinder();
- method public final <T> void readTypedArray(T[], android.os.Parcelable.Creator<T>);
- method public final <T> void readTypedList(java.util.List<T>, android.os.Parcelable.Creator<T>);
- method public final <T> T readTypedObject(android.os.Parcelable.Creator<T>);
- method public final java.lang.Object readValue(java.lang.ClassLoader);
- method public final void recycle();
- method public final void setDataCapacity(int);
- method public final void setDataPosition(int);
- method public final void setDataSize(int);
- method public final void unmarshall(byte[], int, int);
- method public final void writeArray(java.lang.Object[]);
- method public final void writeBinderArray(android.os.IBinder[]);
- method public final void writeBinderList(java.util.List<android.os.IBinder>);
- method public final void writeBooleanArray(boolean[]);
- method public final void writeBundle(android.os.Bundle);
- method public final void writeByte(byte);
- method public final void writeByteArray(byte[]);
- method public final void writeByteArray(byte[], int, int);
- method public final void writeCharArray(char[]);
- method public final void writeDouble(double);
- method public final void writeDoubleArray(double[]);
- method public final void writeException(java.lang.Exception);
- method public final void writeFileDescriptor(java.io.FileDescriptor);
- method public final void writeFloat(float);
- method public final void writeFloatArray(float[]);
- method public final void writeInt(int);
- method public final void writeIntArray(int[]);
- method public final void writeInterfaceToken(java.lang.String);
- method public final void writeList(java.util.List);
- method public final void writeLong(long);
- method public final void writeLongArray(long[]);
- method public final void writeMap(java.util.Map);
- method public final void writeNoException();
- method public final void writeParcelable(android.os.Parcelable, int);
- method public final <T extends android.os.Parcelable> void writeParcelableArray(T[], int);
- method public final void writePersistableBundle(android.os.PersistableBundle);
- method public final void writeSerializable(java.io.Serializable);
- method public final void writeSize(android.util.Size);
- method public final void writeSizeF(android.util.SizeF);
- method public final void writeSparseArray(android.util.SparseArray<java.lang.Object>);
- method public final void writeSparseBooleanArray(android.util.SparseBooleanArray);
- method public final void writeString(java.lang.String);
- method public final void writeStringArray(java.lang.String[]);
- method public final void writeStringList(java.util.List<java.lang.String>);
- method public final void writeStrongBinder(android.os.IBinder);
- method public final void writeStrongInterface(android.os.IInterface);
- method public final <T extends android.os.Parcelable> void writeTypedArray(T[], int);
- method public final <T extends android.os.Parcelable> void writeTypedList(java.util.List<T>);
- method public final <T extends android.os.Parcelable> void writeTypedObject(T, int);
- method public final void writeValue(java.lang.Object);
+ method public java.lang.Object[] readArray(java.lang.ClassLoader);
+ method public java.util.ArrayList readArrayList(java.lang.ClassLoader);
+ method public void readBinderArray(android.os.IBinder[]);
+ method public void readBinderList(java.util.List<android.os.IBinder>);
+ method public void readBooleanArray(boolean[]);
+ method public android.os.Bundle readBundle();
+ method public android.os.Bundle readBundle(java.lang.ClassLoader);
+ method public byte readByte();
+ method public void readByteArray(byte[]);
+ method public void readCharArray(char[]);
+ method public double readDouble();
+ method public void readDoubleArray(double[]);
+ method public void readException();
+ method public void readException(int, java.lang.String);
+ method public android.os.ParcelFileDescriptor readFileDescriptor();
+ method public float readFloat();
+ method public void readFloatArray(float[]);
+ method public java.util.HashMap readHashMap(java.lang.ClassLoader);
+ method public int readInt();
+ method public void readIntArray(int[]);
+ method public void readList(java.util.List, java.lang.ClassLoader);
+ method public long readLong();
+ method public void readLongArray(long[]);
+ method public void readMap(java.util.Map, java.lang.ClassLoader);
+ method public <T extends android.os.Parcelable> T readParcelable(java.lang.ClassLoader);
+ method public android.os.Parcelable[] readParcelableArray(java.lang.ClassLoader);
+ method public android.os.PersistableBundle readPersistableBundle();
+ method public android.os.PersistableBundle readPersistableBundle(java.lang.ClassLoader);
+ method public java.io.Serializable readSerializable();
+ method public android.util.Size readSize();
+ method public android.util.SizeF readSizeF();
+ method public android.util.SparseArray readSparseArray(java.lang.ClassLoader);
+ method public android.util.SparseBooleanArray readSparseBooleanArray();
+ method public java.lang.String readString();
+ method public void readStringArray(java.lang.String[]);
+ method public void readStringList(java.util.List<java.lang.String>);
+ method public android.os.IBinder readStrongBinder();
+ method public <T> void readTypedArray(T[], android.os.Parcelable.Creator<T>);
+ method public <T> void readTypedList(java.util.List<T>, android.os.Parcelable.Creator<T>);
+ method public <T> T readTypedObject(android.os.Parcelable.Creator<T>);
+ method public java.lang.Object readValue(java.lang.ClassLoader);
+ method public void recycle();
+ method public void setDataCapacity(int);
+ method public void setDataPosition(int);
+ method public void setDataSize(int);
+ method public void unmarshall(byte[], int, int);
+ method public void writeArray(java.lang.Object[]);
+ method public void writeBinderArray(android.os.IBinder[]);
+ method public void writeBinderList(java.util.List<android.os.IBinder>);
+ method public void writeBooleanArray(boolean[]);
+ method public void writeBundle(android.os.Bundle);
+ method public void writeByte(byte);
+ method public void writeByteArray(byte[]);
+ method public void writeByteArray(byte[], int, int);
+ method public void writeCharArray(char[]);
+ method public void writeDouble(double);
+ method public void writeDoubleArray(double[]);
+ method public void writeException(java.lang.Exception);
+ method public void writeFileDescriptor(java.io.FileDescriptor);
+ method public void writeFloat(float);
+ method public void writeFloatArray(float[]);
+ method public void writeInt(int);
+ method public void writeIntArray(int[]);
+ method public void writeInterfaceToken(java.lang.String);
+ method public void writeList(java.util.List);
+ method public void writeLong(long);
+ method public void writeLongArray(long[]);
+ method public void writeMap(java.util.Map);
+ method public void writeNoException();
+ method public void writeParcelable(android.os.Parcelable, int);
+ method public <T extends android.os.Parcelable> void writeParcelableArray(T[], int);
+ method public void writePersistableBundle(android.os.PersistableBundle);
+ method public void writeSerializable(java.io.Serializable);
+ method public void writeSize(android.util.Size);
+ method public void writeSizeF(android.util.SizeF);
+ method public void writeSparseArray(android.util.SparseArray<java.lang.Object>);
+ method public void writeSparseBooleanArray(android.util.SparseBooleanArray);
+ method public void writeString(java.lang.String);
+ method public void writeStringArray(java.lang.String[]);
+ method public void writeStringList(java.util.List<java.lang.String>);
+ method public void writeStrongBinder(android.os.IBinder);
+ method public void writeStrongInterface(android.os.IInterface);
+ method public <T extends android.os.Parcelable> void writeTypedArray(T[], int);
+ method public <T extends android.os.Parcelable> void writeTypedList(java.util.List<T>);
+ method public <T extends android.os.Parcelable> void writeTypedObject(T, int);
+ method public void writeValue(java.lang.Object);
field public static final android.os.Parcelable.Creator<java.lang.String> STRING_CREATOR;
}
@@ -34235,7 +34263,7 @@
}
public static final class CalendarContract.Attendees implements android.provider.BaseColumns android.provider.CalendarContract.AttendeesColumns android.provider.CalendarContract.EventsColumns {
- method public static final android.database.Cursor query(android.content.ContentResolver, long, java.lang.String[]);
+ method public static android.database.Cursor query(android.content.ContentResolver, long, java.lang.String[]);
field public static final android.net.Uri CONTENT_URI;
}
@@ -34364,7 +34392,7 @@
}
public static final class CalendarContract.EventDays implements android.provider.CalendarContract.EventDaysColumns {
- method public static final android.database.Cursor query(android.content.ContentResolver, int, int, java.lang.String[]);
+ method public static android.database.Cursor query(android.content.ContentResolver, int, int, java.lang.String[]);
field public static final android.net.Uri CONTENT_URI;
}
@@ -34457,8 +34485,8 @@
}
public static final class CalendarContract.Instances implements android.provider.BaseColumns android.provider.CalendarContract.CalendarColumns android.provider.CalendarContract.EventsColumns {
- method public static final android.database.Cursor query(android.content.ContentResolver, java.lang.String[], long, long);
- method public static final android.database.Cursor query(android.content.ContentResolver, java.lang.String[], long, long, java.lang.String);
+ method public static android.database.Cursor query(android.content.ContentResolver, java.lang.String[], long, long);
+ method public static android.database.Cursor query(android.content.ContentResolver, java.lang.String[], long, long, java.lang.String);
field public static final java.lang.String BEGIN = "begin";
field public static final android.net.Uri CONTENT_BY_DAY_URI;
field public static final android.net.Uri CONTENT_SEARCH_BY_DAY_URI;
@@ -34473,7 +34501,7 @@
}
public static final class CalendarContract.Reminders implements android.provider.BaseColumns android.provider.CalendarContract.EventsColumns android.provider.CalendarContract.RemindersColumns {
- method public static final android.database.Cursor query(android.content.ContentResolver, long, java.lang.String[]);
+ method public static android.database.Cursor query(android.content.ContentResolver, long, java.lang.String[]);
field public static final android.net.Uri CONTENT_URI;
}
@@ -34582,7 +34610,7 @@
method public static deprecated java.lang.Object decodeImProtocol(java.lang.String);
method public static deprecated java.lang.String encodeCustomImProtocol(java.lang.String);
method public static deprecated java.lang.String encodePredefinedImProtocol(int);
- method public static final deprecated java.lang.CharSequence getDisplayLabel(android.content.Context, int, int, java.lang.CharSequence);
+ method public static deprecated java.lang.CharSequence getDisplayLabel(android.content.Context, int, int, java.lang.CharSequence);
field public static final deprecated java.lang.String CONTENT_EMAIL_ITEM_TYPE = "vnd.android.cursor.item/email";
field public static final deprecated java.lang.String CONTENT_EMAIL_TYPE = "vnd.android.cursor.dir/email";
field public static final deprecated android.net.Uri CONTENT_EMAIL_URI;
@@ -34732,7 +34760,7 @@
}
public static final deprecated class Contacts.Organizations implements android.provider.BaseColumns android.provider.Contacts.OrganizationColumns {
- method public static final deprecated java.lang.CharSequence getDisplayLabel(android.content.Context, int, java.lang.CharSequence);
+ method public static deprecated java.lang.CharSequence getDisplayLabel(android.content.Context, int, java.lang.CharSequence);
field public static final deprecated java.lang.String CONTENT_DIRECTORY = "organizations";
field public static final deprecated android.net.Uri CONTENT_URI;
field public static final deprecated java.lang.String DEFAULT_SORT_ORDER = "company, title, isprimary ASC";
@@ -34789,8 +34817,8 @@
}
public static final deprecated class Contacts.Phones implements android.provider.BaseColumns android.provider.Contacts.PeopleColumns android.provider.Contacts.PhonesColumns {
- method public static final deprecated java.lang.CharSequence getDisplayLabel(android.content.Context, int, java.lang.CharSequence, java.lang.CharSequence[]);
- method public static final deprecated java.lang.CharSequence getDisplayLabel(android.content.Context, int, java.lang.CharSequence);
+ method public static deprecated java.lang.CharSequence getDisplayLabel(android.content.Context, int, java.lang.CharSequence, java.lang.CharSequence[]);
+ method public static deprecated java.lang.CharSequence getDisplayLabel(android.content.Context, int, java.lang.CharSequence);
field public static final deprecated android.net.Uri CONTENT_FILTER_URL;
field public static final deprecated java.lang.String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/phone";
field public static final deprecated java.lang.String CONTENT_TYPE = "vnd.android.cursor.dir/phone";
@@ -34930,8 +34958,8 @@
}
public static final class ContactsContract.CommonDataKinds.Email implements android.provider.ContactsContract.CommonDataKinds.CommonColumns android.provider.ContactsContract.DataColumnsWithJoins {
- method public static final java.lang.CharSequence getTypeLabel(android.content.res.Resources, int, java.lang.CharSequence);
- method public static final int getTypeLabelResource(int);
+ method public static java.lang.CharSequence getTypeLabel(android.content.res.Resources, int, java.lang.CharSequence);
+ method public static int getTypeLabelResource(int);
field public static final java.lang.String ADDRESS = "data1";
field public static final android.net.Uri CONTENT_FILTER_URI;
field public static final java.lang.String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/email_v2";
@@ -34951,7 +34979,7 @@
}
public static final class ContactsContract.CommonDataKinds.Event implements android.provider.ContactsContract.CommonDataKinds.CommonColumns android.provider.ContactsContract.DataColumnsWithJoins {
- method public static final java.lang.CharSequence getTypeLabel(android.content.res.Resources, int, java.lang.CharSequence);
+ method public static java.lang.CharSequence getTypeLabel(android.content.res.Resources, int, java.lang.CharSequence);
method public static int getTypeResource(java.lang.Integer);
field public static final java.lang.String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/contact_event";
field public static final java.lang.String EXTRA_ADDRESS_BOOK_INDEX = "android.provider.extra.ADDRESS_BOOK_INDEX";
@@ -34982,10 +35010,10 @@
}
public static final class ContactsContract.CommonDataKinds.Im implements android.provider.ContactsContract.CommonDataKinds.CommonColumns android.provider.ContactsContract.DataColumnsWithJoins {
- method public static final java.lang.CharSequence getProtocolLabel(android.content.res.Resources, int, java.lang.CharSequence);
- method public static final int getProtocolLabelResource(int);
- method public static final java.lang.CharSequence getTypeLabel(android.content.res.Resources, int, java.lang.CharSequence);
- method public static final int getTypeLabelResource(int);
+ method public static java.lang.CharSequence getProtocolLabel(android.content.res.Resources, int, java.lang.CharSequence);
+ method public static int getProtocolLabelResource(int);
+ method public static java.lang.CharSequence getTypeLabel(android.content.res.Resources, int, java.lang.CharSequence);
+ method public static int getTypeLabelResource(int);
field public static final java.lang.String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/im";
field public static final java.lang.String CUSTOM_PROTOCOL = "data6";
field public static final java.lang.String EXTRA_ADDRESS_BOOK_INDEX = "android.provider.extra.ADDRESS_BOOK_INDEX";
@@ -35030,8 +35058,8 @@
}
public static final class ContactsContract.CommonDataKinds.Organization implements android.provider.ContactsContract.CommonDataKinds.CommonColumns android.provider.ContactsContract.DataColumnsWithJoins {
- method public static final java.lang.CharSequence getTypeLabel(android.content.res.Resources, int, java.lang.CharSequence);
- method public static final int getTypeLabelResource(int);
+ method public static java.lang.CharSequence getTypeLabel(android.content.res.Resources, int, java.lang.CharSequence);
+ method public static int getTypeLabelResource(int);
field public static final java.lang.String COMPANY = "data1";
field public static final java.lang.String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/organization";
field public static final java.lang.String DEPARTMENT = "data5";
@@ -35049,8 +35077,8 @@
}
public static final class ContactsContract.CommonDataKinds.Phone implements android.provider.ContactsContract.CommonDataKinds.CommonColumns android.provider.ContactsContract.DataColumnsWithJoins {
- method public static final java.lang.CharSequence getTypeLabel(android.content.res.Resources, int, java.lang.CharSequence);
- method public static final int getTypeLabelResource(int);
+ method public static java.lang.CharSequence getTypeLabel(android.content.res.Resources, int, java.lang.CharSequence);
+ method public static int getTypeLabelResource(int);
field public static final android.net.Uri CONTENT_FILTER_URI;
field public static final java.lang.String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/phone_v2";
field public static final java.lang.String CONTENT_TYPE = "vnd.android.cursor.dir/phone_v2";
@@ -35095,8 +35123,8 @@
}
public static final class ContactsContract.CommonDataKinds.Relation implements android.provider.ContactsContract.CommonDataKinds.CommonColumns android.provider.ContactsContract.DataColumnsWithJoins {
- method public static final java.lang.CharSequence getTypeLabel(android.content.res.Resources, int, java.lang.CharSequence);
- method public static final int getTypeLabelResource(int);
+ method public static java.lang.CharSequence getTypeLabel(android.content.res.Resources, int, java.lang.CharSequence);
+ method public static int getTypeLabelResource(int);
field public static final java.lang.String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/relation";
field public static final java.lang.String EXTRA_ADDRESS_BOOK_INDEX = "android.provider.extra.ADDRESS_BOOK_INDEX";
field public static final java.lang.String EXTRA_ADDRESS_BOOK_INDEX_COUNTS = "android.provider.extra.ADDRESS_BOOK_INDEX_COUNTS";
@@ -35119,8 +35147,8 @@
}
public static final class ContactsContract.CommonDataKinds.SipAddress implements android.provider.ContactsContract.CommonDataKinds.CommonColumns android.provider.ContactsContract.DataColumnsWithJoins {
- method public static final java.lang.CharSequence getTypeLabel(android.content.res.Resources, int, java.lang.CharSequence);
- method public static final int getTypeLabelResource(int);
+ method public static java.lang.CharSequence getTypeLabel(android.content.res.Resources, int, java.lang.CharSequence);
+ method public static int getTypeLabelResource(int);
field public static final java.lang.String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/sip_address";
field public static final java.lang.String EXTRA_ADDRESS_BOOK_INDEX = "android.provider.extra.ADDRESS_BOOK_INDEX";
field public static final java.lang.String EXTRA_ADDRESS_BOOK_INDEX_COUNTS = "android.provider.extra.ADDRESS_BOOK_INDEX_COUNTS";
@@ -35150,8 +35178,8 @@
}
public static final class ContactsContract.CommonDataKinds.StructuredPostal implements android.provider.ContactsContract.CommonDataKinds.CommonColumns android.provider.ContactsContract.DataColumnsWithJoins {
- method public static final java.lang.CharSequence getTypeLabel(android.content.res.Resources, int, java.lang.CharSequence);
- method public static final int getTypeLabelResource(int);
+ method public static java.lang.CharSequence getTypeLabel(android.content.res.Resources, int, java.lang.CharSequence);
+ method public static int getTypeLabelResource(int);
field public static final java.lang.String CITY = "data7";
field public static final java.lang.String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/postal-address_v2";
field public static final java.lang.String CONTENT_TYPE = "vnd.android.cursor.dir/postal-address_v2";
@@ -35978,7 +36006,7 @@
public static final class MediaStore.Audio.Artists.Albums implements android.provider.MediaStore.Audio.AlbumColumns {
ctor public MediaStore.Audio.Artists.Albums();
- method public static final android.net.Uri getContentUri(java.lang.String, long);
+ method public static android.net.Uri getContentUri(java.lang.String, long);
}
public static abstract interface MediaStore.Audio.AudioColumns implements android.provider.MediaStore.MediaColumns {
@@ -36014,7 +36042,7 @@
public static final class MediaStore.Audio.Genres.Members implements android.provider.MediaStore.Audio.AudioColumns {
ctor public MediaStore.Audio.Genres.Members();
- method public static final android.net.Uri getContentUri(java.lang.String, long);
+ method public static android.net.Uri getContentUri(java.lang.String, long);
field public static final java.lang.String AUDIO_ID = "audio_id";
field public static final java.lang.String CONTENT_DIRECTORY = "members";
field public static final java.lang.String DEFAULT_SORT_ORDER = "title_key";
@@ -36050,8 +36078,8 @@
public static final class MediaStore.Audio.Playlists.Members implements android.provider.MediaStore.Audio.AudioColumns {
ctor public MediaStore.Audio.Playlists.Members();
- method public static final android.net.Uri getContentUri(java.lang.String, long);
- method public static final boolean moveItem(android.content.ContentResolver, long, int, int);
+ method public static android.net.Uri getContentUri(java.lang.String, long);
+ method public static boolean moveItem(android.content.ContentResolver, long, int, int);
field public static final java.lang.String AUDIO_ID = "audio_id";
field public static final java.lang.String CONTENT_DIRECTORY = "members";
field public static final java.lang.String DEFAULT_SORT_ORDER = "play_order";
@@ -36074,7 +36102,7 @@
public static final class MediaStore.Files {
ctor public MediaStore.Files();
method public static android.net.Uri getContentUri(java.lang.String);
- method public static final android.net.Uri getContentUri(java.lang.String, long);
+ method public static android.net.Uri getContentUri(java.lang.String, long);
}
public static abstract interface MediaStore.Files.FileColumns implements android.provider.MediaStore.MediaColumns {
@@ -36108,13 +36136,13 @@
public static final class MediaStore.Images.Media implements android.provider.MediaStore.Images.ImageColumns {
ctor public MediaStore.Images.Media();
- method public static final android.graphics.Bitmap getBitmap(android.content.ContentResolver, android.net.Uri) throws java.io.FileNotFoundException, java.io.IOException;
+ method public static android.graphics.Bitmap getBitmap(android.content.ContentResolver, android.net.Uri) throws java.io.FileNotFoundException, java.io.IOException;
method public static android.net.Uri getContentUri(java.lang.String);
- method public static final java.lang.String insertImage(android.content.ContentResolver, java.lang.String, java.lang.String, java.lang.String) throws java.io.FileNotFoundException;
- method public static final java.lang.String insertImage(android.content.ContentResolver, android.graphics.Bitmap, java.lang.String, java.lang.String);
- method public static final android.database.Cursor query(android.content.ContentResolver, android.net.Uri, java.lang.String[]);
- method public static final android.database.Cursor query(android.content.ContentResolver, android.net.Uri, java.lang.String[], java.lang.String, java.lang.String);
- method public static final android.database.Cursor query(android.content.ContentResolver, android.net.Uri, java.lang.String[], java.lang.String, java.lang.String[], java.lang.String);
+ method public static java.lang.String insertImage(android.content.ContentResolver, java.lang.String, java.lang.String, java.lang.String) throws java.io.FileNotFoundException;
+ method public static java.lang.String insertImage(android.content.ContentResolver, android.graphics.Bitmap, java.lang.String, java.lang.String);
+ method public static android.database.Cursor query(android.content.ContentResolver, android.net.Uri, java.lang.String[]);
+ method public static android.database.Cursor query(android.content.ContentResolver, android.net.Uri, java.lang.String[], java.lang.String, java.lang.String);
+ method public static android.database.Cursor query(android.content.ContentResolver, android.net.Uri, java.lang.String[], java.lang.String, java.lang.String[], java.lang.String);
field public static final java.lang.String CONTENT_TYPE = "vnd.android.cursor.dir/image";
field public static final java.lang.String DEFAULT_SORT_ORDER = "bucket_display_name";
field public static final android.net.Uri EXTERNAL_CONTENT_URI;
@@ -36159,7 +36187,7 @@
public static final class MediaStore.Video {
ctor public MediaStore.Video();
- method public static final android.database.Cursor query(android.content.ContentResolver, android.net.Uri, java.lang.String[]);
+ method public static android.database.Cursor query(android.content.ContentResolver, android.net.Uri, java.lang.String[]);
field public static final java.lang.String DEFAULT_SORT_ORDER = "_display_name";
}
@@ -36391,12 +36419,12 @@
method public static long getLong(android.content.ContentResolver, java.lang.String) throws android.provider.Settings.SettingNotFoundException;
method public static java.lang.String getString(android.content.ContentResolver, java.lang.String);
method public static android.net.Uri getUriFor(java.lang.String);
- method public static final deprecated boolean isLocationProviderEnabled(android.content.ContentResolver, java.lang.String);
+ method public static deprecated boolean isLocationProviderEnabled(android.content.ContentResolver, java.lang.String);
method public static boolean putFloat(android.content.ContentResolver, java.lang.String, float);
method public static boolean putInt(android.content.ContentResolver, java.lang.String, int);
method public static boolean putLong(android.content.ContentResolver, java.lang.String, long);
method public static boolean putString(android.content.ContentResolver, java.lang.String, java.lang.String);
- method public static final deprecated void setLocationProviderEnabled(android.content.ContentResolver, java.lang.String, boolean);
+ method public static deprecated void setLocationProviderEnabled(android.content.ContentResolver, java.lang.String, boolean);
field public static final java.lang.String ACCESSIBILITY_DISPLAY_INVERSION_ENABLED = "accessibility_display_inversion_enabled";
field public static final java.lang.String ACCESSIBILITY_ENABLED = "accessibility_enabled";
field public static final deprecated java.lang.String ACCESSIBILITY_SPEAK_PASSWORD = "speak_password";
@@ -38199,6 +38227,37 @@
method public java.security.KeyPair getKeyPair();
}
+ public class ConfirmationAlreadyPresentingException extends java.lang.Exception {
+ ctor public ConfirmationAlreadyPresentingException();
+ ctor public ConfirmationAlreadyPresentingException(java.lang.String);
+ }
+
+ public abstract class ConfirmationCallback {
+ ctor public ConfirmationCallback();
+ method public void onConfirmedByUser(byte[]);
+ method public void onDismissedByApplication();
+ method public void onDismissedByUser();
+ method public void onError(java.lang.Exception);
+ }
+
+ public class ConfirmationDialog {
+ method public void cancelPrompt();
+ method public static boolean isSupported();
+ method public void presentPrompt(java.util.concurrent.Executor, android.security.ConfirmationCallback) throws android.security.ConfirmationAlreadyPresentingException, android.security.ConfirmationNotAvailableException;
+ }
+
+ public static class ConfirmationDialog.Builder {
+ ctor public ConfirmationDialog.Builder();
+ method public android.security.ConfirmationDialog build(android.content.Context);
+ method public android.security.ConfirmationDialog.Builder setExtraData(byte[]);
+ method public android.security.ConfirmationDialog.Builder setPromptText(java.lang.CharSequence);
+ }
+
+ public class ConfirmationNotAvailableException extends java.lang.Exception {
+ ctor public ConfirmationNotAvailableException();
+ ctor public ConfirmationNotAvailableException(java.lang.String);
+ }
+
public final class KeyChain {
ctor public KeyChain();
method public static void choosePrivateKeyAlias(android.app.Activity, android.security.KeyChainAliasCallback, java.lang.String[], java.security.Principal[], java.lang.String, int, java.lang.String);
@@ -38308,6 +38367,7 @@
method public boolean isTrustedUserPresenceRequired();
method public boolean isUserAuthenticationRequired();
method public boolean isUserAuthenticationValidWhileOnBody();
+ method public boolean isUserConfirmationRequired();
}
public static final class KeyGenParameterSpec.Builder {
@@ -38335,6 +38395,7 @@
method public android.security.keystore.KeyGenParameterSpec.Builder setUserAuthenticationRequired(boolean);
method public android.security.keystore.KeyGenParameterSpec.Builder setUserAuthenticationValidWhileOnBody(boolean);
method public android.security.keystore.KeyGenParameterSpec.Builder setUserAuthenticationValidityDurationSeconds(int);
+ method public android.security.keystore.KeyGenParameterSpec.Builder setUserConfirmationRequired(boolean);
}
public class KeyInfo implements java.security.spec.KeySpec {
@@ -38356,6 +38417,7 @@
method public boolean isUserAuthenticationRequired();
method public boolean isUserAuthenticationRequirementEnforcedBySecureHardware();
method public boolean isUserAuthenticationValidWhileOnBody();
+ method public boolean isUserConfirmationRequired();
}
public class KeyNotYetValidException extends java.security.InvalidKeyException {
@@ -38423,6 +38485,7 @@
method public boolean isRandomizedEncryptionRequired();
method public boolean isUserAuthenticationRequired();
method public boolean isUserAuthenticationValidWhileOnBody();
+ method public boolean isUserConfirmationRequired();
}
public static final class KeyProtection.Builder {
@@ -38441,6 +38504,7 @@
method public android.security.keystore.KeyProtection.Builder setUserAuthenticationRequired(boolean);
method public android.security.keystore.KeyProtection.Builder setUserAuthenticationValidWhileOnBody(boolean);
method public android.security.keystore.KeyProtection.Builder setUserAuthenticationValidityDurationSeconds(int);
+ method public android.security.keystore.KeyProtection.Builder setUserConfirmationRequired(boolean);
}
public class StrongBoxUnavailableException extends java.security.ProviderException {
@@ -40392,12 +40456,12 @@
method public void playDtmfTone(char);
method public void postDialContinue(boolean);
method public void pullExternalCall();
- method public final void putExtras(android.os.Bundle);
+ method public void putExtras(android.os.Bundle);
method public void registerCallback(android.telecom.Call.Callback);
method public void registerCallback(android.telecom.Call.Callback, android.os.Handler);
method public void reject(boolean, java.lang.String);
- method public final void removeExtras(java.util.List<java.lang.String>);
- method public final void removeExtras(java.lang.String...);
+ method public void removeExtras(java.util.List<java.lang.String>);
+ method public void removeExtras(java.lang.String...);
method public void respondToRttRequest(int, boolean);
method public void sendCallEvent(java.lang.String, android.os.Bundle);
method public void sendRttRequest();
@@ -40966,23 +41030,23 @@
public final class RemoteConference {
method public void disconnect();
method public java.util.List<android.telecom.RemoteConnection> getConferenceableConnections();
- method public final int getConnectionCapabilities();
- method public final int getConnectionProperties();
- method public final java.util.List<android.telecom.RemoteConnection> getConnections();
+ method public int getConnectionCapabilities();
+ method public int getConnectionProperties();
+ method public java.util.List<android.telecom.RemoteConnection> getConnections();
method public android.telecom.DisconnectCause getDisconnectCause();
- method public final android.os.Bundle getExtras();
- method public final int getState();
+ method public android.os.Bundle getExtras();
+ method public int getState();
method public void hold();
method public void merge();
method public void playDtmfTone(char);
- method public final void registerCallback(android.telecom.RemoteConference.Callback);
- method public final void registerCallback(android.telecom.RemoteConference.Callback, android.os.Handler);
+ method public void registerCallback(android.telecom.RemoteConference.Callback);
+ method public void registerCallback(android.telecom.RemoteConference.Callback, android.os.Handler);
method public void separate(android.telecom.RemoteConnection);
method public void setCallAudioState(android.telecom.CallAudioState);
method public void stopDtmfTone();
method public void swap();
method public void unhold();
- method public final void unregisterCallback(android.telecom.RemoteConference.Callback);
+ method public void unregisterCallback(android.telecom.RemoteConference.Callback);
}
public static abstract class RemoteConference.Callback {
@@ -41011,10 +41075,10 @@
method public int getConnectionCapabilities();
method public int getConnectionProperties();
method public android.telecom.DisconnectCause getDisconnectCause();
- method public final android.os.Bundle getExtras();
+ method public android.os.Bundle getExtras();
method public int getState();
method public android.telecom.StatusHints getStatusHints();
- method public final android.telecom.RemoteConnection.VideoProvider getVideoProvider();
+ method public android.telecom.RemoteConnection.VideoProvider getVideoProvider();
method public int getVideoState();
method public void hold();
method public boolean isRingbackRequested();
@@ -42467,11 +42531,11 @@
}
public final deprecated class SmsManager {
- method public final deprecated java.util.ArrayList<java.lang.String> divideMessage(java.lang.String);
- method public static final deprecated android.telephony.gsm.SmsManager getDefault();
- method public final deprecated void sendDataMessage(java.lang.String, java.lang.String, short, byte[], android.app.PendingIntent, android.app.PendingIntent);
- method public final deprecated void sendMultipartTextMessage(java.lang.String, java.lang.String, java.util.ArrayList<java.lang.String>, java.util.ArrayList<android.app.PendingIntent>, java.util.ArrayList<android.app.PendingIntent>);
- method public final deprecated void sendTextMessage(java.lang.String, java.lang.String, java.lang.String, android.app.PendingIntent, android.app.PendingIntent);
+ method public deprecated java.util.ArrayList<java.lang.String> divideMessage(java.lang.String);
+ method public static deprecated android.telephony.gsm.SmsManager getDefault();
+ method public deprecated void sendDataMessage(java.lang.String, java.lang.String, short, byte[], android.app.PendingIntent, android.app.PendingIntent);
+ method public deprecated void sendMultipartTextMessage(java.lang.String, java.lang.String, java.util.ArrayList<java.lang.String>, java.util.ArrayList<android.app.PendingIntent>, java.util.ArrayList<android.app.PendingIntent>);
+ method public deprecated void sendTextMessage(java.lang.String, java.lang.String, java.lang.String, android.app.PendingIntent, android.app.PendingIntent);
field public static final deprecated int RESULT_ERROR_GENERIC_FAILURE = 1; // 0x1
field public static final deprecated int RESULT_ERROR_NO_SERVICE = 4; // 0x4
field public static final deprecated int RESULT_ERROR_NULL_PDU = 3; // 0x3
@@ -46530,76 +46594,76 @@
public final class MotionEvent extends android.view.InputEvent implements android.os.Parcelable {
method public static java.lang.String actionToString(int);
- method public final void addBatch(long, float, float, float, float, int);
- method public final void addBatch(long, android.view.MotionEvent.PointerCoords[], int);
+ method public void addBatch(long, float, float, float, float, int);
+ method public void addBatch(long, android.view.MotionEvent.PointerCoords[], int);
method public static int axisFromString(java.lang.String);
method public static java.lang.String axisToString(int);
- method public final int findPointerIndex(int);
- method public final int getAction();
- method public final int getActionButton();
- method public final int getActionIndex();
- method public final int getActionMasked();
- method public final float getAxisValue(int);
- method public final float getAxisValue(int, int);
- method public final int getButtonState();
- method public final int getDeviceId();
- method public final long getDownTime();
- method public final int getEdgeFlags();
- method public final long getEventTime();
- method public final int getFlags();
- method public final float getHistoricalAxisValue(int, int);
- method public final float getHistoricalAxisValue(int, int, int);
- method public final long getHistoricalEventTime(int);
- method public final float getHistoricalOrientation(int);
- method public final float getHistoricalOrientation(int, int);
- method public final void getHistoricalPointerCoords(int, int, android.view.MotionEvent.PointerCoords);
- method public final float getHistoricalPressure(int);
- method public final float getHistoricalPressure(int, int);
- method public final float getHistoricalSize(int);
- method public final float getHistoricalSize(int, int);
- method public final float getHistoricalToolMajor(int);
- method public final float getHistoricalToolMajor(int, int);
- method public final float getHistoricalToolMinor(int);
- method public final float getHistoricalToolMinor(int, int);
- method public final float getHistoricalTouchMajor(int);
- method public final float getHistoricalTouchMajor(int, int);
- method public final float getHistoricalTouchMinor(int);
- method public final float getHistoricalTouchMinor(int, int);
- method public final float getHistoricalX(int);
- method public final float getHistoricalX(int, int);
- method public final float getHistoricalY(int);
- method public final float getHistoricalY(int, int);
- method public final int getHistorySize();
- method public final int getMetaState();
- method public final float getOrientation();
- method public final float getOrientation(int);
- method public final void getPointerCoords(int, android.view.MotionEvent.PointerCoords);
- method public final int getPointerCount();
- method public final int getPointerId(int);
- method public final void getPointerProperties(int, android.view.MotionEvent.PointerProperties);
- method public final float getPressure();
- method public final float getPressure(int);
- method public final float getRawX();
- method public final float getRawY();
- method public final float getSize();
- method public final float getSize(int);
- method public final int getSource();
- method public final float getToolMajor();
- method public final float getToolMajor(int);
- method public final float getToolMinor();
- method public final float getToolMinor(int);
- method public final int getToolType(int);
- method public final float getTouchMajor();
- method public final float getTouchMajor(int);
- method public final float getTouchMinor();
- method public final float getTouchMinor(int);
- method public final float getX();
- method public final float getX(int);
- method public final float getXPrecision();
- method public final float getY();
- method public final float getY(int);
- method public final float getYPrecision();
- method public final boolean isButtonPressed(int);
+ method public int findPointerIndex(int);
+ method public int getAction();
+ method public int getActionButton();
+ method public int getActionIndex();
+ method public int getActionMasked();
+ method public float getAxisValue(int);
+ method public float getAxisValue(int, int);
+ method public int getButtonState();
+ method public int getDeviceId();
+ method public long getDownTime();
+ method public int getEdgeFlags();
+ method public long getEventTime();
+ method public int getFlags();
+ method public float getHistoricalAxisValue(int, int);
+ method public float getHistoricalAxisValue(int, int, int);
+ method public long getHistoricalEventTime(int);
+ method public float getHistoricalOrientation(int);
+ method public float getHistoricalOrientation(int, int);
+ method public void getHistoricalPointerCoords(int, int, android.view.MotionEvent.PointerCoords);
+ method public float getHistoricalPressure(int);
+ method public float getHistoricalPressure(int, int);
+ method public float getHistoricalSize(int);
+ method public float getHistoricalSize(int, int);
+ method public float getHistoricalToolMajor(int);
+ method public float getHistoricalToolMajor(int, int);
+ method public float getHistoricalToolMinor(int);
+ method public float getHistoricalToolMinor(int, int);
+ method public float getHistoricalTouchMajor(int);
+ method public float getHistoricalTouchMajor(int, int);
+ method public float getHistoricalTouchMinor(int);
+ method public float getHistoricalTouchMinor(int, int);
+ method public float getHistoricalX(int);
+ method public float getHistoricalX(int, int);
+ method public float getHistoricalY(int);
+ method public float getHistoricalY(int, int);
+ method public int getHistorySize();
+ method public int getMetaState();
+ method public float getOrientation();
+ method public float getOrientation(int);
+ method public void getPointerCoords(int, android.view.MotionEvent.PointerCoords);
+ method public int getPointerCount();
+ method public int getPointerId(int);
+ method public void getPointerProperties(int, android.view.MotionEvent.PointerProperties);
+ method public float getPressure();
+ method public float getPressure(int);
+ method public float getRawX();
+ method public float getRawY();
+ method public float getSize();
+ method public float getSize(int);
+ method public int getSource();
+ method public float getToolMajor();
+ method public float getToolMajor(int);
+ method public float getToolMinor();
+ method public float getToolMinor(int);
+ method public int getToolType(int);
+ method public float getTouchMajor();
+ method public float getTouchMajor(int);
+ method public float getTouchMinor();
+ method public float getTouchMinor(int);
+ method public float getX();
+ method public float getX(int);
+ method public float getXPrecision();
+ method public float getY();
+ method public float getY(int);
+ method public float getYPrecision();
+ method public boolean isButtonPressed(int);
method public static android.view.MotionEvent obtain(long, long, int, int, android.view.MotionEvent.PointerProperties[], android.view.MotionEvent.PointerCoords[], int, int, float, float, int, int, int, int);
method public static deprecated android.view.MotionEvent obtain(long, long, int, int, int[], android.view.MotionEvent.PointerCoords[], int, float, float, int, int, int, int);
method public static android.view.MotionEvent obtain(long, long, int, float, float, float, float, int, float, float, int, int);
@@ -46607,13 +46671,13 @@
method public static android.view.MotionEvent obtain(long, long, int, float, float, int);
method public static android.view.MotionEvent obtain(android.view.MotionEvent);
method public static android.view.MotionEvent obtainNoHistory(android.view.MotionEvent);
- method public final void offsetLocation(float, float);
- method public final void recycle();
- method public final void setAction(int);
- method public final void setEdgeFlags(int);
- method public final void setLocation(float, float);
- method public final void setSource(int);
- method public final void transform(android.graphics.Matrix);
+ method public void offsetLocation(float, float);
+ method public void recycle();
+ method public void setAction(int);
+ method public void setEdgeFlags(int);
+ method public void setLocation(float, float);
+ method public void setSource(int);
+ method public void transform(android.graphics.Matrix);
method public void writeToParcel(android.os.Parcel, int);
field public static final int ACTION_BUTTON_PRESS = 11; // 0xb
field public static final int ACTION_BUTTON_RELEASE = 12; // 0xc
@@ -47174,7 +47238,9 @@
method public int getNextFocusRightId();
method public int getNextFocusUpId();
method public android.view.View.OnFocusChangeListener getOnFocusChangeListener();
+ method public int getOutlineAmbientShadowColor();
method public android.view.ViewOutlineProvider getOutlineProvider();
+ method public int getOutlineSpotShadowColor();
method public int getOverScrollMode();
method public android.view.ViewOverlay getOverlay();
method public int getPaddingBottom();
@@ -47496,7 +47562,9 @@
method public void setOnScrollChangeListener(android.view.View.OnScrollChangeListener);
method public void setOnSystemUiVisibilityChangeListener(android.view.View.OnSystemUiVisibilityChangeListener);
method public void setOnTouchListener(android.view.View.OnTouchListener);
+ method public void setOutlineAmbientShadowColor(int);
method public void setOutlineProvider(android.view.ViewOutlineProvider);
+ method public void setOutlineSpotShadowColor(int);
method public void setOverScrollMode(int);
method public void setPadding(int, int, int, int);
method public void setPaddingRelative(int, int, int, int);
@@ -48331,9 +48399,9 @@
method public void addOnTouchModeChangeListener(android.view.ViewTreeObserver.OnTouchModeChangeListener);
method public void addOnWindowAttachListener(android.view.ViewTreeObserver.OnWindowAttachListener);
method public void addOnWindowFocusChangeListener(android.view.ViewTreeObserver.OnWindowFocusChangeListener);
- method public final void dispatchOnDraw();
- method public final void dispatchOnGlobalLayout();
- method public final boolean dispatchOnPreDraw();
+ method public void dispatchOnDraw();
+ method public void dispatchOnGlobalLayout();
+ method public boolean dispatchOnPreDraw();
method public boolean isAlive();
method public deprecated void removeGlobalOnLayoutListener(android.view.ViewTreeObserver.OnGlobalLayoutListener);
method public void removeOnDrawListener(android.view.ViewTreeObserver.OnDrawListener);
@@ -50594,7 +50662,7 @@
ctor public URLUtil();
method public static java.lang.String composeSearchUrl(java.lang.String, java.lang.String, java.lang.String);
method public static byte[] decode(byte[]) throws java.lang.IllegalArgumentException;
- method public static final java.lang.String guessFileName(java.lang.String, java.lang.String, java.lang.String);
+ method public static java.lang.String guessFileName(java.lang.String, java.lang.String, java.lang.String);
method public static java.lang.String guessUrl(java.lang.String);
method public static boolean isAboutUrl(java.lang.String);
method public static boolean isAssetUrl(java.lang.String);
@@ -55663,7 +55731,7 @@
}
public static final class Character.UnicodeBlock extends java.lang.Character.Subset {
- method public static final java.lang.Character.UnicodeBlock forName(java.lang.String);
+ method public static java.lang.Character.UnicodeBlock forName(java.lang.String);
method public static java.lang.Character.UnicodeBlock of(char);
method public static java.lang.Character.UnicodeBlock of(int);
field public static final java.lang.Character.UnicodeBlock AEGEAN_NUMBERS;
@@ -55890,7 +55958,7 @@
}
public static final class Character.UnicodeScript extends java.lang.Enum {
- method public static final java.lang.Character.UnicodeScript forName(java.lang.String);
+ method public static java.lang.Character.UnicodeScript forName(java.lang.String);
method public static java.lang.Character.UnicodeScript of(int);
method public static java.lang.Character.UnicodeScript valueOf(java.lang.String);
method public static final java.lang.Character.UnicodeScript[] values();
@@ -57553,6 +57621,7 @@
method public boolean enqueue();
method public T get();
method public boolean isEnqueued();
+ method public static void reachabilityFence(java.lang.Object);
}
public class ReferenceQueue<T> {
@@ -58705,8 +58774,8 @@
ctor public URL(java.net.URL, java.lang.String) throws java.net.MalformedURLException;
ctor public URL(java.net.URL, java.lang.String, java.net.URLStreamHandler) throws java.net.MalformedURLException;
method public java.lang.String getAuthority();
- method public final java.lang.Object getContent() throws java.io.IOException;
- method public final java.lang.Object getContent(java.lang.Class[]) throws java.io.IOException;
+ method public java.lang.Object getContent() throws java.io.IOException;
+ method public java.lang.Object getContent(java.lang.Class[]) throws java.io.IOException;
method public int getDefaultPort();
method public java.lang.String getFile();
method public java.lang.String getHost();
@@ -58719,7 +58788,7 @@
method public synchronized int hashCode();
method public java.net.URLConnection openConnection() throws java.io.IOException;
method public java.net.URLConnection openConnection(java.net.Proxy) throws java.io.IOException;
- method public final java.io.InputStream openStream() throws java.io.IOException;
+ method public java.io.InputStream openStream() throws java.io.IOException;
method public boolean sameFile(java.net.URL);
method public static void setURLStreamHandlerFactory(java.net.URLStreamHandlerFactory);
method public java.lang.String toExternalForm();
@@ -63375,13 +63444,13 @@
method public int getOffset();
method public int next();
method public int previous();
- method public static final int primaryOrder(int);
+ method public static int primaryOrder(int);
method public void reset();
- method public static final short secondaryOrder(int);
+ method public static short secondaryOrder(int);
method public void setOffset(int);
method public void setText(java.lang.String);
method public void setText(java.text.CharacterIterator);
- method public static final short tertiaryOrder(int);
+ method public static short tertiaryOrder(int);
field public static final int NULLORDER = -1; // 0xffffffff
}
@@ -64662,7 +64731,7 @@
}
public final class HijrahDate implements java.time.chrono.ChronoLocalDate java.io.Serializable java.time.temporal.Temporal java.time.temporal.TemporalAdjuster {
- method public final java.time.chrono.ChronoLocalDateTime<java.time.chrono.HijrahDate> atTime(java.time.LocalTime);
+ method public java.time.chrono.ChronoLocalDateTime<java.time.chrono.HijrahDate> atTime(java.time.LocalTime);
method public static java.time.chrono.HijrahDate from(java.time.temporal.TemporalAccessor);
method public java.time.chrono.HijrahChronology getChronology();
method public java.time.chrono.HijrahEra getEra();
@@ -64749,7 +64818,7 @@
}
public final class JapaneseDate implements java.time.chrono.ChronoLocalDate java.io.Serializable java.time.temporal.Temporal java.time.temporal.TemporalAdjuster {
- method public final java.time.chrono.ChronoLocalDateTime<java.time.chrono.JapaneseDate> atTime(java.time.LocalTime);
+ method public java.time.chrono.ChronoLocalDateTime<java.time.chrono.JapaneseDate> atTime(java.time.LocalTime);
method public static java.time.chrono.JapaneseDate from(java.time.temporal.TemporalAccessor);
method public java.time.chrono.JapaneseChronology getChronology();
method public java.time.chrono.JapaneseEra getEra();
@@ -64805,7 +64874,7 @@
}
public final class MinguoDate implements java.time.chrono.ChronoLocalDate java.io.Serializable java.time.temporal.Temporal java.time.temporal.TemporalAdjuster {
- method public final java.time.chrono.ChronoLocalDateTime<java.time.chrono.MinguoDate> atTime(java.time.LocalTime);
+ method public java.time.chrono.ChronoLocalDateTime<java.time.chrono.MinguoDate> atTime(java.time.LocalTime);
method public static java.time.chrono.MinguoDate from(java.time.temporal.TemporalAccessor);
method public java.time.chrono.MinguoChronology getChronology();
method public java.time.chrono.MinguoEra getEra();
@@ -64858,7 +64927,7 @@
}
public final class ThaiBuddhistDate implements java.time.chrono.ChronoLocalDate java.io.Serializable java.time.temporal.Temporal java.time.temporal.TemporalAdjuster {
- method public final java.time.chrono.ChronoLocalDateTime<java.time.chrono.ThaiBuddhistDate> atTime(java.time.LocalTime);
+ method public java.time.chrono.ChronoLocalDateTime<java.time.chrono.ThaiBuddhistDate> atTime(java.time.LocalTime);
method public static java.time.chrono.ThaiBuddhistDate from(java.time.temporal.TemporalAccessor);
method public java.time.chrono.ThaiBuddhistChronology getChronology();
method public java.time.chrono.ThaiBuddhistEra getEra();
@@ -64910,8 +64979,8 @@
method public <T> T parse(java.lang.CharSequence, java.time.temporal.TemporalQuery<T>);
method public java.time.temporal.TemporalAccessor parseBest(java.lang.CharSequence, java.time.temporal.TemporalQuery<?>...);
method public java.time.temporal.TemporalAccessor parseUnresolved(java.lang.CharSequence, java.text.ParsePosition);
- method public static final java.time.temporal.TemporalQuery<java.time.Period> parsedExcessDays();
- method public static final java.time.temporal.TemporalQuery<java.lang.Boolean> parsedLeapSecond();
+ method public static java.time.temporal.TemporalQuery<java.time.Period> parsedExcessDays();
+ method public static java.time.temporal.TemporalQuery<java.lang.Boolean> parsedLeapSecond();
method public java.text.Format toFormat();
method public java.text.Format toFormat(java.time.temporal.TemporalQuery<?>);
method public java.time.format.DateTimeFormatter withChronology(java.time.chrono.Chronology);
@@ -66360,15 +66429,15 @@
method public java.lang.String getCountry();
method public static java.util.Locale getDefault();
method public static java.util.Locale getDefault(java.util.Locale.Category);
- method public final java.lang.String getDisplayCountry();
+ method public java.lang.String getDisplayCountry();
method public java.lang.String getDisplayCountry(java.util.Locale);
- method public final java.lang.String getDisplayLanguage();
+ method public java.lang.String getDisplayLanguage();
method public java.lang.String getDisplayLanguage(java.util.Locale);
- method public final java.lang.String getDisplayName();
+ method public java.lang.String getDisplayName();
method public java.lang.String getDisplayName(java.util.Locale);
method public java.lang.String getDisplayScript();
method public java.lang.String getDisplayScript(java.util.Locale);
- method public final java.lang.String getDisplayVariant();
+ method public java.lang.String getDisplayVariant();
method public java.lang.String getDisplayVariant(java.util.Locale);
method public java.lang.String getExtension(char);
method public java.util.Set<java.lang.Character> getExtensionKeys();
@@ -66389,7 +66458,6 @@
method public static synchronized void setDefault(java.util.Locale.Category, java.util.Locale);
method public java.util.Locale stripExtensions();
method public java.lang.String toLanguageTag();
- method public final java.lang.String toString();
field public static final java.util.Locale CANADA;
field public static final java.util.Locale CANADA_FRENCH;
field public static final java.util.Locale CHINA;
@@ -70575,7 +70643,6 @@
public class ExemptionMechanism {
ctor protected ExemptionMechanism(javax.crypto.ExemptionMechanismSpi, java.security.Provider, java.lang.String);
- method protected void finalize();
method public final byte[] genExemptionBlob() throws javax.crypto.ExemptionMechanismException, java.lang.IllegalStateException;
method public final int genExemptionBlob(byte[]) throws javax.crypto.ExemptionMechanismException, java.lang.IllegalStateException, javax.crypto.ShortBufferException;
method public final int genExemptionBlob(byte[], int) throws javax.crypto.ExemptionMechanismException, java.lang.IllegalStateException, javax.crypto.ShortBufferException;
diff --git a/api/system-current.txt b/api/system-current.txt
index 88ee1c0..87269d0 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -2691,10 +2691,10 @@
package android.media.tv {
public final class TvContentRatingSystemInfo implements android.os.Parcelable {
- method public static final android.media.tv.TvContentRatingSystemInfo createTvContentRatingSystemInfo(int, android.content.pm.ApplicationInfo);
+ method public static android.media.tv.TvContentRatingSystemInfo createTvContentRatingSystemInfo(int, android.content.pm.ApplicationInfo);
method public int describeContents();
- method public final android.net.Uri getXmlUri();
- method public final boolean isSystemDefined();
+ method public android.net.Uri getXmlUri();
+ method public boolean isSystemDefined();
method public void writeToParcel(android.os.Parcel, int);
}
@@ -4675,15 +4675,15 @@
}
public final deprecated class Phone {
- method public final void addListener(android.telecom.Phone.Listener);
- method public final boolean canAddCall();
- method public final deprecated android.telecom.AudioState getAudioState();
- method public final android.telecom.CallAudioState getCallAudioState();
- method public final java.util.List<android.telecom.Call> getCalls();
- method public final void removeListener(android.telecom.Phone.Listener);
+ method public void addListener(android.telecom.Phone.Listener);
+ method public boolean canAddCall();
+ method public deprecated android.telecom.AudioState getAudioState();
+ method public android.telecom.CallAudioState getCallAudioState();
+ method public java.util.List<android.telecom.Call> getCalls();
+ method public void removeListener(android.telecom.Phone.Listener);
method public void requestBluetoothAudio(java.lang.String);
- method public final void setAudioRoute(int);
- method public final void setMuted(boolean);
+ method public void setAudioRoute(int);
+ method public void setMuted(boolean);
}
public static abstract class Phone.Listener {
diff --git a/api/test-current.txt b/api/test-current.txt
index d834cf7..bf00343 100644
--- a/api/test-current.txt
+++ b/api/test-current.txt
@@ -995,8 +995,8 @@
}
public final class MotionEvent extends android.view.InputEvent implements android.os.Parcelable {
- method public final void setActionButton(int);
- method public final void setButtonState(int);
+ method public void setActionButton(int);
+ method public void setButtonState(int);
}
public class View implements android.view.accessibility.AccessibilityEventSource android.graphics.drawable.Drawable.Callback android.view.KeyEvent.Callback {
diff --git a/cmds/statsd/tools/dogfood/Android.mk b/cmds/statsd/tools/dogfood/Android.mk
index 32a85b1..a65095f 100644
--- a/cmds/statsd/tools/dogfood/Android.mk
+++ b/cmds/statsd/tools/dogfood/Android.mk
@@ -27,6 +27,7 @@
LOCAL_PROTOC_OPTIMIZE_TYPE := lite
LOCAL_PRIVILEGED_MODULE := true
LOCAL_DEX_PREOPT := false
+LOCAL_CERTIFICATE := platform
LOCAL_PROGUARD_ENABLED := disabled
include $(BUILD_PACKAGE)
diff --git a/cmds/statsd/tools/dogfood/AndroidManifest.xml b/cmds/statsd/tools/dogfood/AndroidManifest.xml
index 7bfde40..cd76c9d 100644
--- a/cmds/statsd/tools/dogfood/AndroidManifest.xml
+++ b/cmds/statsd/tools/dogfood/AndroidManifest.xml
@@ -18,6 +18,7 @@
-->
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.android.statsd.dogfood"
+ android:sharedUserId="android.uid.system"
android:versionCode="1"
android:versionName="1.0" >
diff --git a/cmds/statsd/tools/dogfood/res/raw/statsd_baseline_config b/cmds/statsd/tools/dogfood/res/raw/statsd_baseline_config
index c1c3914..d050061 100644
--- a/cmds/statsd/tools/dogfood/res/raw/statsd_baseline_config
+++ b/cmds/statsd/tools/dogfood/res/raw/statsd_baseline_config
Binary files differ
diff --git a/cmds/svc/src/com/android/commands/svc/UsbCommand.java b/cmds/svc/src/com/android/commands/svc/UsbCommand.java
index 34f6d7d..3893be4 100644
--- a/cmds/svc/src/com/android/commands/svc/UsbCommand.java
+++ b/cmds/svc/src/com/android/commands/svc/UsbCommand.java
@@ -21,7 +21,6 @@
import android.hardware.usb.UsbManager;
import android.os.RemoteException;
import android.os.ServiceManager;
-import android.os.SystemProperties;
public class UsbCommand extends Svc.Command {
public UsbCommand() {
@@ -37,41 +36,41 @@
public String longHelp() {
return shortHelp() + "\n"
+ "\n"
- + "usage: svc usb setFunction [function] [usbDataUnlocked=false]\n"
- + " Set the current usb function and optionally the data lock state.\n\n"
+ + "usage: svc usb setFunctions [function]\n"
+ + " Set the current usb function. If function is blank, sets to charging.\n"
+ " svc usb setScreenUnlockedFunctions [function]\n"
- + " Sets the functions which, if the device was charging,"
- + " become current on screen unlock.\n"
- + " svc usb getFunction\n"
- + " Gets the list of currently enabled functions\n";
+ + " Sets the functions which, if the device was charging, become current on"
+ + "screen unlock. If function is blank, turn off this feature.\n"
+ + " svc usb getFunctions\n"
+ + " Gets the list of currently enabled functions\n\n"
+ + "possible values of [function] are any of 'mtp', 'ptp', 'rndis', 'midi'\n";
}
@Override
public void run(String[] args) {
- boolean validCommand = false;
if (args.length >= 2) {
- if ("setFunction".equals(args[1])) {
- IUsbManager usbMgr = IUsbManager.Stub.asInterface(ServiceManager.getService(
- Context.USB_SERVICE));
- boolean unlockData = false;
- if (args.length >= 4) {
- unlockData = Boolean.valueOf(args[3]);
- }
+ IUsbManager usbMgr = IUsbManager.Stub.asInterface(ServiceManager.getService(
+ Context.USB_SERVICE));
+ if ("setFunctions".equals(args[1])) {
try {
- usbMgr.setCurrentFunction((args.length >=3 ? args[2] : null), unlockData);
+ usbMgr.setCurrentFunctions(UsbManager.usbFunctionsFromString(
+ args.length >= 3 ? args[2] : ""));
} catch (RemoteException e) {
System.err.println("Error communicating with UsbManager: " + e);
}
return;
- } else if ("getFunction".equals(args[1])) {
- System.err.println(SystemProperties.get("sys.usb.config"));
+ } else if ("getFunctions".equals(args[1])) {
+ try {
+ System.err.println(
+ UsbManager.usbFunctionsToString(usbMgr.getCurrentFunctions()));
+ } catch (RemoteException e) {
+ System.err.println("Error communicating with UsbManager: " + e);
+ }
return;
} else if ("setScreenUnlockedFunctions".equals(args[1])) {
- IUsbManager usbMgr = IUsbManager.Stub.asInterface(ServiceManager.getService(
- Context.USB_SERVICE));
try {
- usbMgr.setScreenUnlockedFunctions((args.length >= 3 ? args[2] :
- UsbManager.USB_FUNCTION_NONE));
+ usbMgr.setScreenUnlockedFunctions(UsbManager.usbFunctionsFromString(
+ args.length >= 3 ? args[2] : ""));
} catch (RemoteException e) {
System.err.println("Error communicating with UsbManager: " + e);
}
diff --git a/core/java/android/app/Activity.java b/core/java/android/app/Activity.java
index 7bfb20f..fdb0ac9 100644
--- a/core/java/android/app/Activity.java
+++ b/core/java/android/app/Activity.java
@@ -7143,7 +7143,10 @@
boolean isApiWarningEnabled = SystemProperties.getInt("ro.art.hiddenapi.warning", 0) == 1;
if (isAppDebuggable || isApiWarningEnabled) {
- if (VMRuntime.getRuntime().hasUsedHiddenApi()) {
+ if (!mMainThread.mHiddenApiWarningShown && VMRuntime.getRuntime().hasUsedHiddenApi()) {
+ // Only show the warning once per process.
+ mMainThread.mHiddenApiWarningShown = true;
+
String appName = getApplicationInfo().loadLabel(getPackageManager())
.toString();
String warning = "Detected problems with API compatiblity\n"
diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java
index e8535cd1..29e091b 100644
--- a/core/java/android/app/ActivityThread.java
+++ b/core/java/android/app/ActivityThread.java
@@ -291,6 +291,7 @@
boolean mJitEnabled = false;
boolean mSomeActivitiesChanged = false;
boolean mUpdatingSystemConfig = false;
+ /* package */ boolean mHiddenApiWarningShown = false;
// These can be accessed by multiple threads; mResourcesManager is the lock.
// XXX For now we keep around information about all packages we have
diff --git a/core/java/android/app/slice/SliceManager.java b/core/java/android/app/slice/SliceManager.java
index 2fa9d8e..e5f3eae 100644
--- a/core/java/android/app/slice/SliceManager.java
+++ b/core/java/android/app/slice/SliceManager.java
@@ -314,6 +314,59 @@
}
/**
+ * Turns a slice intent into a slice uri. Expects an explicit intent. If there is no
+ * {@link android.content.ContentProvider} associated with the given intent this will throw
+ * {@link IllegalArgumentException}.
+ *
+ * @param intent The intent associated with a slice.
+ * @return The Slice Uri provided by the app or null if none is given.
+ * @see Slice
+ * @see SliceProvider#onMapIntentToUri(Intent)
+ * @see Intent
+ */
+ public @Nullable Uri mapIntentToUri(@NonNull Intent intent) {
+ Preconditions.checkNotNull(intent, "intent");
+ Preconditions.checkArgument(intent.getComponent() != null || intent.getPackage() != null,
+ "Slice intent must be explicit %s", intent);
+ ContentResolver resolver = mContext.getContentResolver();
+
+ // Check if the intent has data for the slice uri on it and use that
+ final Uri intentData = intent.getData();
+ if (intentData != null && SliceProvider.SLICE_TYPE.equals(resolver.getType(intentData))) {
+ return intentData;
+ }
+ // Otherwise ask the app
+ List<ResolveInfo> providers =
+ mContext.getPackageManager().queryIntentContentProviders(intent, 0);
+ if (providers == null || providers.isEmpty()) {
+ throw new IllegalArgumentException("Unable to resolve intent " + intent);
+ }
+ String authority = providers.get(0).providerInfo.authority;
+ Uri uri = new Uri.Builder().scheme(ContentResolver.SCHEME_CONTENT)
+ .authority(authority).build();
+ IContentProvider provider = resolver.acquireProvider(uri);
+ if (provider == null) {
+ throw new IllegalArgumentException("Unknown URI " + uri);
+ }
+ try {
+ Bundle extras = new Bundle();
+ extras.putParcelable(SliceProvider.EXTRA_INTENT, intent);
+ final Bundle res = provider.call(mContext.getPackageName(),
+ SliceProvider.METHOD_MAP_ONLY_INTENT, null, extras);
+ if (res == null) {
+ return null;
+ }
+ return res.getParcelable(SliceProvider.EXTRA_SLICE);
+ } catch (RemoteException e) {
+ // Arbitrary and not worth documenting, as Activity
+ // Manager will kill this process shortly anyway.
+ return null;
+ } finally {
+ resolver.releaseProvider(provider);
+ }
+ }
+
+ /**
* Turns a slice intent into slice content. Expects an explicit intent. If there is no
* {@link android.content.ContentProvider} associated with the given intent this will throw
* {@link IllegalArgumentException}.
@@ -329,7 +382,7 @@
@NonNull List<SliceSpec> supportedSpecs) {
Preconditions.checkNotNull(intent, "intent");
Preconditions.checkArgument(intent.getComponent() != null || intent.getPackage() != null,
- "Slice intent must be explicit " + intent);
+ "Slice intent must be explicit %s", intent);
ContentResolver resolver = mContext.getContentResolver();
// Check if the intent has data for the slice uri on it and use that
@@ -340,7 +393,7 @@
// Otherwise ask the app
List<ResolveInfo> providers =
mContext.getPackageManager().queryIntentContentProviders(intent, 0);
- if (providers == null) {
+ if (providers == null || providers.isEmpty()) {
throw new IllegalArgumentException("Unable to resolve intent " + intent);
}
String authority = providers.get(0).providerInfo.authority;
diff --git a/core/java/android/app/slice/SliceProvider.java b/core/java/android/app/slice/SliceProvider.java
index 336bd47..af43032 100644
--- a/core/java/android/app/slice/SliceProvider.java
+++ b/core/java/android/app/slice/SliceProvider.java
@@ -114,6 +114,10 @@
/**
* @hide
*/
+ public static final String METHOD_MAP_ONLY_INTENT = "map_only";
+ /**
+ * @hide
+ */
public static final String METHOD_PIN = "pin";
/**
* @hide
@@ -341,6 +345,13 @@
b.putParcelable(EXTRA_SLICE, null);
}
return b;
+ } else if (method.equals(METHOD_MAP_ONLY_INTENT)) {
+ Intent intent = extras.getParcelable(EXTRA_INTENT);
+ if (intent == null) return null;
+ Uri uri = onMapIntentToUri(intent);
+ Bundle b = new Bundle();
+ b.putParcelable(EXTRA_SLICE, uri);
+ return b;
} else if (method.equals(METHOD_PIN)) {
Uri uri = getUriWithoutUserId(extras.getParcelable(EXTRA_BIND_URI));
if (Binder.getCallingUid() != Process.SYSTEM_UID) {
diff --git a/core/java/android/hardware/usb/IUsbManager.aidl b/core/java/android/hardware/usb/IUsbManager.aidl
index 398dda1..91bbdc7 100644
--- a/core/java/android/hardware/usb/IUsbManager.aidl
+++ b/core/java/android/hardware/usb/IUsbManager.aidl
@@ -88,18 +88,22 @@
/* Returns true if the specified USB function is enabled. */
boolean isFunctionEnabled(String function);
- /* Sets the current USB function as well as whether USB data
- * (for example, MTP exposed pictures) should be made available
- * on the USB connection. Unlocking data should only be done with
- * user involvement, since exposing pictures or other data could
- * leak sensitive user information.
- */
+ /* Sets the current USB function. */
+ void setCurrentFunctions(long functions);
+
+ /* Compatibility version of setCurrentFunctions(long). */
void setCurrentFunction(String function, boolean usbDataUnlocked);
+ /* Gets the current USB functions. */
+ long getCurrentFunctions();
+
/* Sets the screen unlocked USB function(s), which will be set automatically
* when the screen is unlocked.
*/
- void setScreenUnlockedFunctions(String function);
+ void setScreenUnlockedFunctions(long functions);
+
+ /* Gets the current screen unlocked functions. */
+ long getScreenUnlockedFunctions();
/* Allow USB debugging from the attached host. If alwaysAllow is true, add the
* the public key to list of host keys that the user has approved.
diff --git a/core/java/android/hardware/usb/UsbManager.java b/core/java/android/hardware/usb/UsbManager.java
index 7617c2b..8daecac 100644
--- a/core/java/android/hardware/usb/UsbManager.java
+++ b/core/java/android/hardware/usb/UsbManager.java
@@ -28,6 +28,7 @@
import android.content.ComponentName;
import android.content.Context;
import android.content.pm.PackageManager.NameNotFoundException;
+import android.hardware.usb.gadget.V1_0.GadgetFunction;
import android.os.Bundle;
import android.os.ParcelFileDescriptor;
import android.os.Process;
@@ -37,6 +38,8 @@
import com.android.internal.util.Preconditions;
import java.util.HashMap;
+import java.util.Map;
+import java.util.StringJoiner;
/**
* This class allows you to access the state of USB and communicate with USB devices.
@@ -70,7 +73,7 @@
* MTP function is enabled
* <li> {@link #USB_FUNCTION_PTP} boolean extra indicating whether the
* PTP function is enabled
- * <li> {@link #USB_FUNCTION_PTP} boolean extra indicating whether the
+ * <li> {@link #USB_FUNCTION_ACCESSORY} boolean extra indicating whether the
* accessory function is enabled
* <li> {@link #USB_FUNCTION_AUDIO_SOURCE} boolean extra indicating whether the
* audio source function is enabled
@@ -196,8 +199,7 @@
/**
* A placeholder indicating that no USB function is being specified.
- * Used to distinguish between selecting no function vs. the default function in
- * {@link #setCurrentFunction(String)}.
+ * Used for compatibility with old init scripts to indicate no functions vs. charging function.
*
* {@hide}
*/
@@ -298,6 +300,69 @@
*/
public static final String EXTRA_PERMISSION_GRANTED = "permission";
+ /**
+ * Code for the charging usb function. Passed into {@link #setCurrentFunctions(long)}
+ * {@hide}
+ */
+ public static final long FUNCTION_NONE = 0;
+
+ /**
+ * Code for the mtp usb function. Passed as a mask into {@link #setCurrentFunctions(long)}
+ * {@hide}
+ */
+ public static final long FUNCTION_MTP = GadgetFunction.MTP;
+
+ /**
+ * Code for the ptp usb function. Passed as a mask into {@link #setCurrentFunctions(long)}
+ * {@hide}
+ */
+ public static final long FUNCTION_PTP = GadgetFunction.PTP;
+
+ /**
+ * Code for the rndis usb function. Passed as a mask into {@link #setCurrentFunctions(long)}
+ * {@hide}
+ */
+ public static final long FUNCTION_RNDIS = GadgetFunction.RNDIS;
+
+ /**
+ * Code for the midi usb function. Passed as a mask into {@link #setCurrentFunctions(long)}
+ * {@hide}
+ */
+ public static final long FUNCTION_MIDI = GadgetFunction.MIDI;
+
+ /**
+ * Code for the accessory usb function.
+ * {@hide}
+ */
+ public static final long FUNCTION_ACCESSORY = GadgetFunction.ACCESSORY;
+
+ /**
+ * Code for the audio source usb function.
+ * {@hide}
+ */
+ public static final long FUNCTION_AUDIO_SOURCE = GadgetFunction.AUDIO_SOURCE;
+
+ /**
+ * Code for the adb usb function.
+ * {@hide}
+ */
+ public static final long FUNCTION_ADB = GadgetFunction.ADB;
+
+ private static final long SETTABLE_FUNCTIONS = FUNCTION_MTP | FUNCTION_PTP | FUNCTION_RNDIS
+ | FUNCTION_MIDI;
+
+ private static final Map<String, Long> FUNCTION_NAME_TO_CODE = new HashMap<>();
+
+ static {
+ FUNCTION_NAME_TO_CODE.put(UsbManager.USB_FUNCTION_MTP, FUNCTION_MTP);
+ FUNCTION_NAME_TO_CODE.put(UsbManager.USB_FUNCTION_PTP, FUNCTION_PTP);
+ FUNCTION_NAME_TO_CODE.put(UsbManager.USB_FUNCTION_RNDIS, FUNCTION_RNDIS);
+ FUNCTION_NAME_TO_CODE.put(UsbManager.USB_FUNCTION_MIDI, FUNCTION_MIDI);
+ FUNCTION_NAME_TO_CODE.put(UsbManager.USB_FUNCTION_ACCESSORY, FUNCTION_ACCESSORY);
+ FUNCTION_NAME_TO_CODE.put(UsbManager.USB_FUNCTION_AUDIO_SOURCE, FUNCTION_AUDIO_SOURCE);
+ FUNCTION_NAME_TO_CODE.put(UsbManager.USB_FUNCTION_ADB, FUNCTION_ADB);
+ }
+
private final Context mContext;
private final IUsbManager mService;
@@ -548,15 +613,14 @@
* services offered by the device.
* </p>
*
+ * @deprecated use getCurrentFunctions() instead.
* @param function name of the USB function
* @return true if the USB function is enabled
*
* {@hide}
*/
+ @Deprecated
public boolean isFunctionEnabled(String function) {
- if (mService == null) {
- return false;
- }
try {
return mService.isFunctionEnabled(function);
} catch (RemoteException e) {
@@ -565,7 +629,7 @@
}
/**
- * Sets the current USB function when in device mode.
+ * Sets the current USB functions when in device mode.
* <p>
* USB functions represent interfaces which are published to the host to access
* services offered by the device.
@@ -574,27 +638,59 @@
* automatically activate additional functions such as {@link #USB_FUNCTION_ADB}
* or {@link #USB_FUNCTION_ACCESSORY} based on other settings and states.
* </p><p>
- * The allowed values are: {@link #USB_FUNCTION_NONE}, {@link #USB_FUNCTION_AUDIO_SOURCE},
- * {@link #USB_FUNCTION_MIDI}, {@link #USB_FUNCTION_MTP}, {@link #USB_FUNCTION_PTP},
- * or {@link #USB_FUNCTION_RNDIS}.
- * </p><p>
- * Also sets whether USB data (for example, MTP exposed pictures) should be made available
- * on the USB connection when in device mode. Unlocking usb data should only be done with
- * user involvement, since exposing pictures or other data could leak sensitive
- * user information.
+ * An argument of 0 indicates that the device is charging, and can pick any
+ * appropriate function for that purpose.
* </p><p>
* Note: This function is asynchronous and may fail silently without applying
* the requested changes.
* </p>
*
- * @param function name of the USB function, or null to restore the default function
- * @param usbDataUnlocked whether user data is accessible
+ * @param functions the USB function(s) to set, as a bitwise mask.
+ * Must satisfy {@link UsbManager#areSettableFunctions}
*
* {@hide}
*/
- public void setCurrentFunction(String function, boolean usbDataUnlocked) {
+ public void setCurrentFunctions(long functions) {
try {
- mService.setCurrentFunction(function, usbDataUnlocked);
+ mService.setCurrentFunctions(functions);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
+ /**
+ * Sets the current USB functions when in device mode.
+ *
+ * @deprecated use setCurrentFunctions(long) instead.
+ * @param functions the USB function(s) to set.
+ * @param usbDataUnlocked unused
+
+ * {@hide}
+ */
+ @Deprecated
+ public void setCurrentFunction(String functions, boolean usbDataUnlocked) {
+ try {
+ mService.setCurrentFunction(functions, usbDataUnlocked);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
+ /**
+ * Returns the current USB functions in device mode.
+ * <p>
+ * This function returns the state of primary USB functions and can return a
+ * mask containing any usb function(s) except for ADB.
+ * </p>
+ *
+ * @return The currently enabled functions, in a bitwise mask.
+ * A zero mask indicates that the current function is the charging function.
+ *
+ * {@hide}
+ */
+ public long getCurrentFunctions() {
+ try {
+ return mService.getCurrentFunctions();
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
@@ -604,23 +700,37 @@
* Sets the screen unlocked functions, which are persisted and set as the current functions
* whenever the screen is unlocked.
* <p>
- * The allowed values are: {@link #USB_FUNCTION_NONE},
- * {@link #USB_FUNCTION_MIDI}, {@link #USB_FUNCTION_MTP}, {@link #USB_FUNCTION_PTP},
- * or {@link #USB_FUNCTION_RNDIS}.
- * {@link #USB_FUNCTION_NONE} has the effect of switching off this feature, so functions
+ * A zero mask has the effect of switching off this feature, so functions
* no longer change on screen unlock.
* </p><p>
* Note: When the screen is on, this method will apply given functions as current functions,
* which is asynchronous and may fail silently without applying the requested changes.
* </p>
*
- * @param function function to set as default
+ * @param functions functions to set, in a bitwise mask.
+ * Must satisfy {@link UsbManager#areSettableFunctions}
*
* {@hide}
*/
- public void setScreenUnlockedFunctions(String function) {
+ public void setScreenUnlockedFunctions(long functions) {
try {
- mService.setScreenUnlockedFunctions(function);
+ mService.setScreenUnlockedFunctions(functions);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
+ /**
+ * Gets the current screen unlocked functions.
+ *
+ * @return The currently set screen enabled functions.
+ * A zero mask indicates that the screen unlocked functions feature is not enabled.
+ *
+ * {@hide}
+ */
+ public long getScreenUnlockedFunctions() {
+ try {
+ return mService.getScreenUnlockedFunctions();
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
@@ -719,51 +829,71 @@
}
}
- /** @hide */
- public static String addFunction(String functions, String function) {
- if (USB_FUNCTION_NONE.equals(functions)) {
- return function;
- }
- if (!containsFunction(functions, function)) {
- if (functions.length() > 0) {
- functions += ",";
- }
- functions += function;
- }
- return functions;
+ /**
+ * Returns whether the given functions are valid inputs to UsbManager.
+ * Currently the empty functions or any of MTP, PTP, RNDIS, MIDI are accepted.
+ *
+ * @return Whether the mask is settable.
+ *
+ * {@hide}
+ */
+ public static boolean areSettableFunctions(long functions) {
+ return functions == FUNCTION_NONE
+ || ((~SETTABLE_FUNCTIONS & functions) == 0 && Long.bitCount(functions) == 1);
}
- /** @hide */
- public static String removeFunction(String functions, String function) {
- String[] split = functions.split(",");
- for (int i = 0; i < split.length; i++) {
- if (function.equals(split[i])) {
- split[i] = null;
- }
+ /**
+ * Converts the given function mask to string. Maintains ordering with respect to init scripts.
+ *
+ * @return String representation of given mask
+ *
+ * {@hide}
+ */
+ public static String usbFunctionsToString(long functions) {
+ StringJoiner joiner = new StringJoiner(",");
+ if ((functions & FUNCTION_MTP) != 0) {
+ joiner.add(UsbManager.USB_FUNCTION_MTP);
}
- if (split.length == 1 && split[0] == null) {
- return USB_FUNCTION_NONE;
+ if ((functions & FUNCTION_PTP) != 0) {
+ joiner.add(UsbManager.USB_FUNCTION_PTP);
}
- StringBuilder builder = new StringBuilder();
- for (int i = 0; i < split.length; i++) {
- String s = split[i];
- if (s != null) {
- if (builder.length() > 0) {
- builder.append(",");
- }
- builder.append(s);
- }
+ if ((functions & FUNCTION_RNDIS) != 0) {
+ joiner.add(UsbManager.USB_FUNCTION_RNDIS);
}
- return builder.toString();
+ if ((functions & FUNCTION_MIDI) != 0) {
+ joiner.add(UsbManager.USB_FUNCTION_MIDI);
+ }
+ if ((functions & FUNCTION_ACCESSORY) != 0) {
+ joiner.add(UsbManager.USB_FUNCTION_ACCESSORY);
+ }
+ if ((functions & FUNCTION_AUDIO_SOURCE) != 0) {
+ joiner.add(UsbManager.USB_FUNCTION_AUDIO_SOURCE);
+ }
+ if ((functions & FUNCTION_ADB) != 0) {
+ joiner.add(UsbManager.USB_FUNCTION_ADB);
+ }
+ return joiner.toString();
}
- /** @hide */
- public static boolean containsFunction(String functions, String function) {
- int index = functions.indexOf(function);
- if (index < 0) return false;
- if (index > 0 && functions.charAt(index - 1) != ',') return false;
- int charAfter = index + function.length();
- if (charAfter < functions.length() && functions.charAt(charAfter) != ',') return false;
- return true;
+ /**
+ * Parses a string of usb functions that are comma separated.
+ *
+ * @return A mask of all valid functions in the string
+ *
+ * {@hide}
+ */
+ public static long usbFunctionsFromString(String functions) {
+ if (functions == null || functions.equals(USB_FUNCTION_NONE)) {
+ return FUNCTION_NONE;
+ }
+ long ret = 0;
+ for (String function : functions.split(",")) {
+ if (FUNCTION_NAME_TO_CODE.containsKey(function)) {
+ ret |= FUNCTION_NAME_TO_CODE.get(function);
+ } else if (function.length() > 0) {
+ throw new IllegalArgumentException("Invalid usb function " + functions);
+ }
+ }
+ return ret;
}
}
diff --git a/core/java/android/security/ConfirmationAlreadyPresentingException.java b/core/java/android/security/ConfirmationAlreadyPresentingException.java
new file mode 100644
index 0000000..ae4ec5a
--- /dev/null
+++ b/core/java/android/security/ConfirmationAlreadyPresentingException.java
@@ -0,0 +1,29 @@
+/*
+ * Copyright 2018 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 android.security;
+
+/**
+ * This exception is thrown when presenting a prompt fails because another prompt is already
+ * being presented.
+ */
+public class ConfirmationAlreadyPresentingException extends Exception {
+ public ConfirmationAlreadyPresentingException() {}
+
+ public ConfirmationAlreadyPresentingException(String message) {
+ super(message);
+ }
+}
diff --git a/core/java/android/security/ConfirmationCallback.java b/core/java/android/security/ConfirmationCallback.java
new file mode 100644
index 0000000..4670bce
--- /dev/null
+++ b/core/java/android/security/ConfirmationCallback.java
@@ -0,0 +1,54 @@
+/*
+ * Copyright 2018 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 android.security;
+
+import android.annotation.NonNull;
+
+/**
+ * Callback class used when signaling that a prompt is no longer being presented.
+ */
+public abstract class ConfirmationCallback {
+ /**
+ * Called when the requested prompt was accepted by the user.
+ *
+ * The format of 'dataThatWasConfirmed' parameter is a <a href="http://cbor.io/">CBOR</a>
+ * encoded map (type 5) with (at least) the keys <strong>prompt</strong> and
+ * <strong>extra</strong>. The keys are encoded as CBOR text string (type 3). The value of
+ * promptText is encoded as CBOR text string (type 3), and the value of extraData is encoded as
+ * CBOR byte string (type 2). Other keys may be added in the future.
+ *
+ * @param dataThatWasConfirmed the data that was confirmed, see above for the format.
+ */
+ public void onConfirmedByUser(@NonNull byte[] dataThatWasConfirmed) {}
+
+ /**
+ * Called when the requested prompt was dismissed (not accepted) by the user.
+ */
+ public void onDismissedByUser() {}
+
+ /**
+ * Called when the requested prompt was dismissed by the application.
+ */
+ public void onDismissedByApplication() {}
+
+ /**
+ * Called when the requested prompt was dismissed because of a low-level error.
+ *
+ * @param e an exception representing the error.
+ */
+ public void onError(Exception e) {}
+}
diff --git a/core/java/android/security/ConfirmationDialog.java b/core/java/android/security/ConfirmationDialog.java
new file mode 100644
index 0000000..e9df370
--- /dev/null
+++ b/core/java/android/security/ConfirmationDialog.java
@@ -0,0 +1,283 @@
+/*
+ * Copyright 2018 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 android.security;
+
+import android.annotation.NonNull;
+import android.content.Context;
+import android.text.TextUtils;
+import android.util.Log;
+
+import java.util.Locale;
+import java.util.concurrent.Executor;
+
+/**
+ * Class used for displaying confirmation prompts.
+ *
+ * <p>Confirmation prompts are prompts shown to the user to confirm a given text and are
+ * implemented in a way that a positive response indicates with high confidence that the user has
+ * seen the given text, even if the Android framework (including the kernel) was
+ * compromised. Implementing confirmation prompts with these guarantees requires dedicated
+ * hardware-support and may not always be available.
+ *
+ * <p>Confirmation prompts are typically used with an external entitity - the <i>Relying Party</i> -
+ * in the following way. The setup steps are as follows:
+ * <ul>
+ * <li> Before first use, the application generates a key-pair with the
+ * {@link android.security.keystore.KeyGenParameterSpec.Builder#setUserConfirmationRequired
+ * CONFIRMATION tag} set. Device attestation,
+ * e.g. {@link java.security.KeyStore#getCertificateChain getCertificateChain()}, is used to
+ * generate a certificate chain that includes the public key (<code>Kpub</code> in the following)
+ * of the newly generated key.
+ * <li> The application sends <code>Kpub</code> and the certificate chain resulting from device
+ * attestation to the <i>Relying Party</i>.
+ * <li> The <i>Relying Party</i> validates the certificate chain which involves checking the root
+ * certificate is what is expected (e.g. a certificate from Google), each certificate signs the
+ * next one in the chain, ending with <code>Kpub</code>, and that the attestation certificate
+ * asserts that <code>Kpub</code> has the
+ * {@link android.security.keystore.KeyGenParameterSpec.Builder#setUserConfirmationRequired
+ * CONFIRMATION tag} set.
+ * Additionally the relying party stores <code>Kpub</code> and associates it with the device
+ * it was received from.
+ * </ul>
+ *
+ * <p>The <i>Relying Party</i> is typically an external device (for example connected via
+ * Bluetooth) or application server.
+ *
+ * <p>Before executing a transaction which requires a high assurance of user content, the
+ * application does the following:
+ * <ul>
+ * <li> The application gets a cryptographic nonce from the <i>Relying Party</i> and passes this as
+ * the <code>extraData</code> (via the Builder helper class) to the
+ * {@link #presentPrompt presentPrompt()} method. The <i>Relying Party</i> stores the nonce locally
+ * since it'll use it in a later step.
+ * <li> If the user approves the prompt a <i>Confirmation Response</i> is returned in the
+ * {@link ConfirmationCallback#onConfirmedByUser onConfirmedByUser(byte[])} callback as the
+ * <code>dataThatWasConfirmed</code> parameter. This blob contains the text that was shown to the
+ * user, the <code>extraData</code> parameter, and possibly other data.
+ * <li> The application signs the <i>Confirmation Response</i> with the previously created key and
+ * sends the blob and the signature to the <i>Relying Party</i>.
+ * <li> The <i>Relying Party</i> checks that the signature was made with <code>Kpub</code> and then
+ * extracts <code>promptText</code> matches what is expected and <code>extraData</code> matches the
+ * previously created nonce. If all checks passes, the transaction is executed.
+ * </ul>
+ *
+ * <p>A common way of implementing the "<code>promptText</code> is what is expected" check in the
+ * last bullet, is to have the <i>Relying Party</i> generate <code>promptText</code> and store it
+ * along the nonce in the <code>extraData</code> blob.
+ */
+public class ConfirmationDialog {
+ private static final String TAG = "ConfirmationDialog";
+
+ private CharSequence mPromptText;
+ private byte[] mExtraData;
+ private ConfirmationCallback mCallback;
+ private Executor mExecutor;
+
+ private final KeyStore mKeyStore = KeyStore.getInstance();
+
+ private void doCallback(int responseCode, byte[] dataThatWasConfirmed,
+ ConfirmationCallback callback) {
+ switch (responseCode) {
+ case KeyStore.CONFIRMATIONUI_OK:
+ callback.onConfirmedByUser(dataThatWasConfirmed);
+ break;
+
+ case KeyStore.CONFIRMATIONUI_CANCELED:
+ callback.onDismissedByUser();
+ break;
+
+ case KeyStore.CONFIRMATIONUI_ABORTED:
+ callback.onDismissedByApplication();
+ break;
+
+ case KeyStore.CONFIRMATIONUI_SYSTEM_ERROR:
+ callback.onError(new Exception("System error returned by ConfirmationUI."));
+ break;
+
+ default:
+ callback.onError(new Exception("Unexpected responseCode=" + responseCode
+ + " from onConfirmtionPromptCompleted() callback."));
+ break;
+ }
+ }
+
+ private final android.os.IBinder mCallbackBinder =
+ new android.security.IConfirmationPromptCallback.Stub() {
+ @Override
+ public void onConfirmationPromptCompleted(
+ int responseCode, final byte[] dataThatWasConfirmed)
+ throws android.os.RemoteException {
+ if (mCallback != null) {
+ ConfirmationCallback callback = mCallback;
+ Executor executor = mExecutor;
+ mCallback = null;
+ mExecutor = null;
+ if (executor == null) {
+ doCallback(responseCode, dataThatWasConfirmed, callback);
+ } else {
+ executor.execute(new Runnable() {
+ @Override
+ public void run() {
+ doCallback(responseCode, dataThatWasConfirmed, callback);
+ }
+ });
+ }
+ }
+ }
+ };
+
+ /**
+ * A builder that collects arguments, to be shown on the system-provided confirmation dialog.
+ */
+ public static class Builder {
+
+ private CharSequence mPromptText;
+ private byte[] mExtraData;
+
+ /**
+ * Creates a builder for the confirmation dialog.
+ */
+ public Builder() {
+ }
+
+ /**
+ * Sets the prompt text for the dialog.
+ *
+ * @param promptText the text to present in the prompt.
+ * @return the builder.
+ */
+ public Builder setPromptText(CharSequence promptText) {
+ mPromptText = promptText;
+ return this;
+ }
+
+ /**
+ * Sets the extra data for the dialog.
+ *
+ * @param extraData data to include in the response data.
+ * @return the builder.
+ */
+ public Builder setExtraData(byte[] extraData) {
+ mExtraData = extraData;
+ return this;
+ }
+
+ /**
+ * Creates a {@link ConfirmationDialog} with the arguments supplied to this builder.
+ *
+ * @param context the application context
+ * @return a {@link ConfirmationDialog}
+ * @throws IllegalArgumentException if any of the required fields are not set.
+ */
+ public ConfirmationDialog build(Context context) {
+ if (TextUtils.isEmpty(mPromptText)) {
+ throw new IllegalArgumentException("prompt text must be set and non-empty");
+ }
+ if (mExtraData == null) {
+ throw new IllegalArgumentException("extraData must be set");
+ }
+ return new ConfirmationDialog(mPromptText, mExtraData);
+ }
+ }
+
+ private ConfirmationDialog(CharSequence promptText, byte[] extraData) {
+ mPromptText = promptText;
+ mExtraData = extraData;
+ }
+
+ /**
+ * Requests a confirmation prompt to be presented to the user.
+ *
+ * When the prompt is no longer being presented, one of the methods in
+ * {@link ConfirmationCallback} is called on the supplied callback object.
+ *
+ * @param executor the executor identifying the thread that will receive the callback.
+ * @param callback the callback to use when the dialog is done showing.
+ * @throws IllegalArgumentException if the prompt text is too long or malfomed.
+ * @throws ConfirmationAlreadyPresentingException if another prompt is being presented.
+ * @throws ConfirmationNotAvailableException if confirmation prompts are not supported.
+ */
+ public void presentPrompt(@NonNull Executor executor, @NonNull ConfirmationCallback callback)
+ throws ConfirmationAlreadyPresentingException,
+ ConfirmationNotAvailableException {
+ if (mCallback != null) {
+ throw new ConfirmationAlreadyPresentingException();
+ }
+ mCallback = callback;
+ mExecutor = executor;
+
+ int uiOptionsAsFlags = 0;
+ // TODO: set AccessibilityInverted, AccessibilityMagnified in uiOptionsAsFlags as needed.
+ String locale = Locale.getDefault().toLanguageTag();
+ int responseCode = mKeyStore.presentConfirmationPrompt(
+ mCallbackBinder, mPromptText.toString(), mExtraData, locale, uiOptionsAsFlags);
+ switch (responseCode) {
+ case KeyStore.CONFIRMATIONUI_OK:
+ return;
+
+ case KeyStore.CONFIRMATIONUI_OPERATION_PENDING:
+ throw new ConfirmationAlreadyPresentingException();
+
+ case KeyStore.CONFIRMATIONUI_UNIMPLEMENTED:
+ throw new ConfirmationNotAvailableException();
+
+ case KeyStore.CONFIRMATIONUI_UIERROR:
+ throw new IllegalArgumentException();
+
+ default:
+ // Unexpected error code.
+ Log.w(TAG,
+ "Unexpected responseCode=" + responseCode
+ + " from presentConfirmationPrompt() call.");
+ throw new IllegalArgumentException();
+ }
+ }
+
+ /**
+ * Cancels a prompt currently being displayed.
+ *
+ * On success, the
+ * {@link ConfirmationCallback#onDismissedByApplication onDismissedByApplication()} method on
+ * the supplied callback object will be called asynchronously.
+ *
+ * @throws IllegalStateException if no prompt is currently being presented.
+ */
+ public void cancelPrompt() {
+ int responseCode = mKeyStore.cancelConfirmationPrompt(mCallbackBinder);
+ if (responseCode == KeyStore.CONFIRMATIONUI_OK) {
+ return;
+ } else if (responseCode == KeyStore.CONFIRMATIONUI_OPERATION_PENDING) {
+ throw new IllegalStateException();
+ } else {
+ // Unexpected error code.
+ Log.w(TAG,
+ "Unexpected responseCode=" + responseCode
+ + " from cancelConfirmationPrompt() call.");
+ throw new IllegalStateException();
+ }
+ }
+
+ /**
+ * Checks if the device supports confirmation prompts.
+ *
+ * @return true if confirmation prompts are supported by the device.
+ */
+ public static boolean isSupported() {
+ // TODO: read and return system property.
+ return true;
+ }
+}
diff --git a/core/java/android/security/ConfirmationNotAvailableException.java b/core/java/android/security/ConfirmationNotAvailableException.java
new file mode 100644
index 0000000..8d0e672
--- /dev/null
+++ b/core/java/android/security/ConfirmationNotAvailableException.java
@@ -0,0 +1,30 @@
+/*
+ * Copyright 2018 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 android.security;
+
+/**
+ * This exception is thrown when presenting a prompt fails because the the environment lacks
+ * facilities for showing confirmations.
+ */
+public class ConfirmationNotAvailableException extends Exception {
+ public ConfirmationNotAvailableException() {
+ }
+
+ public ConfirmationNotAvailableException(String message) {
+ super(message);
+ }
+}
diff --git a/core/java/android/security/keymaster/KeymasterDefs.java b/core/java/android/security/keymaster/KeymasterDefs.java
index 3464370..1d13335 100644
--- a/core/java/android/security/keymaster/KeymasterDefs.java
+++ b/core/java/android/security/keymaster/KeymasterDefs.java
@@ -74,6 +74,7 @@
public static final int KM_TAG_AUTH_TIMEOUT = KM_UINT | 505;
public static final int KM_TAG_ALLOW_WHILE_ON_BODY = KM_BOOL | 506;
public static final int KM_TAG_TRUSTED_USER_PRESENCE_REQUIRED = KM_BOOL | 507;
+ public static final int KM_TAG_TRUSTED_CONFIRMATION_REQUIRED = KM_BOOL | 508;
public static final int KM_TAG_ALL_APPLICATIONS = KM_BOOL | 600;
public static final int KM_TAG_APPLICATION_ID = KM_BYTES | 601;
diff --git a/core/java/android/service/autofill/AutofillService.java b/core/java/android/service/autofill/AutofillService.java
index 917efa8..12aa64e 100644
--- a/core/java/android/service/autofill/AutofillService.java
+++ b/core/java/android/service/autofill/AutofillService.java
@@ -468,9 +468,8 @@
* <p>Typically, field classification can be used to detect fields that can be autofilled with
* user data that is not associated with a specific app—such as email and physical
* address. Once the service identifies that a such field was manually filled by the user, the
- * service could use this signal to improve its heuristics, either locally (i.e., in the same
- * device) or globally (i.e., by crowdsourcing the results back to the service's server so it can
- * be used by other users).
+ * service could use this signal to improve its heuristics on subsequent requests (for example, by
+ * infering which resource ids are associated with known fields).
*
* <p>The field classification workflow involves 4 steps:
*
@@ -481,8 +480,8 @@
* <li>Identify which fields should be analysed by calling
* {@link FillResponse.Builder#setFieldClassificationIds(AutofillId...)}.
* <li>Verify the results through {@link FillEventHistory.Event#getFieldsClassification()}.
- * <li>Use the results to dynamically create {@link Dataset} or {@link SaveInfo} objects in future
- * requests.
+ * <li>Use the results to dynamically create {@link Dataset} or {@link SaveInfo} objects in
+ * subsequent requests.
* </ol>
*
* <p>The field classification is an expensive operation and should be used carefully, otherwise it
diff --git a/core/java/android/service/autofill/CustomDescription.java b/core/java/android/service/autofill/CustomDescription.java
index b8e8b19..fb468a8 100644
--- a/core/java/android/service/autofill/CustomDescription.java
+++ b/core/java/android/service/autofill/CustomDescription.java
@@ -173,7 +173,10 @@
}
/**
- * Updates the {@link RemoteViews presentation template} when a condition is satisfied.
+ * Updates the {@link RemoteViews presentation template} when a condition is satisfied by
+ * applying a series of remote view operations. This allows dynamic customization of the
+ * portion of the save UI that is controlled by the autofill service. Such dynamic
+ * customization is based on the content of target views.
*
* <p>The updates are applied in the sequence they are added, after the
* {@link #addChild(int, Transformation) transformations} are applied to the children
diff --git a/core/java/android/service/autofill/Dataset.java b/core/java/android/service/autofill/Dataset.java
index 266bcda..f32dee1 100644
--- a/core/java/android/service/autofill/Dataset.java
+++ b/core/java/android/service/autofill/Dataset.java
@@ -29,7 +29,6 @@
import com.android.internal.util.Preconditions;
-import java.io.Serializable;
import java.util.ArrayList;
import java.util.regex.Pattern;
@@ -99,7 +98,7 @@
private final ArrayList<AutofillId> mFieldIds;
private final ArrayList<AutofillValue> mFieldValues;
private final ArrayList<RemoteViews> mFieldPresentations;
- private final ArrayList<Pattern> mFieldFilters;
+ private final ArrayList<DatasetFieldFilter> mFieldFilters;
private final RemoteViews mPresentation;
private final IntentSender mAuthentication;
@Nullable String mId;
@@ -132,7 +131,7 @@
/** @hide */
@Nullable
- public Pattern getFilter(int index) {
+ public DatasetFieldFilter getFilter(int index) {
return mFieldFilters.get(index);
}
@@ -189,7 +188,7 @@
private ArrayList<AutofillId> mFieldIds;
private ArrayList<AutofillValue> mFieldValues;
private ArrayList<RemoteViews> mFieldPresentations;
- private ArrayList<Pattern> mFieldFilters;
+ private ArrayList<DatasetFieldFilter> mFieldFilters;
private RemoteViews mPresentation;
private IntentSender mAuthentication;
private boolean mDestroyed;
@@ -363,19 +362,21 @@
* @param value the value to be autofilled. Pass {@code null} if you do not have the value
* but the target view is a logical part of the dataset. For example, if
* the dataset needs authentication and you have no access to the value.
- * @param filter regex used to determine if the dataset should be shown in the autofill UI.
+ * @param filter regex used to determine if the dataset should be shown in the autofill UI;
+ * when {@code null}, it disables filtering on that dataset (this is the recommended
+ * approach when {@code value} is not {@code null} and field contains sensitive data
+ * such as passwords).
*
* @return this builder.
* @throws IllegalStateException if the builder was constructed without a
* {@link RemoteViews presentation}.
*/
public @NonNull Builder setValue(@NonNull AutofillId id, @Nullable AutofillValue value,
- @NonNull Pattern filter) {
+ @Nullable Pattern filter) {
throwIfDestroyed();
- Preconditions.checkNotNull(filter, "filter cannot be null");
Preconditions.checkState(mPresentation != null,
"Dataset presentation not set on constructor");
- setLifeTheUniverseAndEverything(id, value, null, filter);
+ setLifeTheUniverseAndEverything(id, value, null, new DatasetFieldFilter(filter));
return this;
}
@@ -398,23 +399,26 @@
* @param value the value to be autofilled. Pass {@code null} if you do not have the value
* but the target view is a logical part of the dataset. For example, if
* the dataset needs authentication and you have no access to the value.
+ * @param filter regex used to determine if the dataset should be shown in the autofill UI;
+ * when {@code null}, it disables filtering on that dataset (this is the recommended
+ * approach when {@code value} is not {@code null} and field contains sensitive data
+ * such as passwords).
* @param presentation the presentation used to visualize this field.
- * @param filter regex used to determine if the dataset should be shown in the autofill UI.
*
* @return this builder.
*/
public @NonNull Builder setValue(@NonNull AutofillId id, @Nullable AutofillValue value,
- @NonNull Pattern filter, @NonNull RemoteViews presentation) {
+ @Nullable Pattern filter, @NonNull RemoteViews presentation) {
throwIfDestroyed();
- Preconditions.checkNotNull(filter, "filter cannot be null");
Preconditions.checkNotNull(presentation, "presentation cannot be null");
- setLifeTheUniverseAndEverything(id, value, presentation, filter);
+ setLifeTheUniverseAndEverything(id, value, presentation,
+ new DatasetFieldFilter(filter));
return this;
}
private void setLifeTheUniverseAndEverything(@NonNull AutofillId id,
@Nullable AutofillValue value, @Nullable RemoteViews presentation,
- @Nullable Pattern filter) {
+ @Nullable DatasetFieldFilter filter) {
Preconditions.checkNotNull(id, "id cannot be null");
if (mFieldIds != null) {
final int existingIdx = mFieldIds.indexOf(id);
@@ -477,8 +481,8 @@
parcel.writeParcelable(mPresentation, flags);
parcel.writeTypedList(mFieldIds, flags);
parcel.writeTypedList(mFieldValues, flags);
- parcel.writeParcelableList(mFieldPresentations, flags);
- parcel.writeSerializable(mFieldFilters);
+ parcel.writeTypedList(mFieldPresentations, flags);
+ parcel.writeTypedList(mFieldFilters, flags);
parcel.writeParcelable(mAuthentication, flags);
parcel.writeString(mId);
}
@@ -493,22 +497,19 @@
final Builder builder = (presentation == null)
? new Builder()
: new Builder(presentation);
- final ArrayList<AutofillId> ids = parcel.createTypedArrayList(AutofillId.CREATOR);
+ final ArrayList<AutofillId> ids =
+ parcel.createTypedArrayList(AutofillId.CREATOR);
final ArrayList<AutofillValue> values =
parcel.createTypedArrayList(AutofillValue.CREATOR);
- final ArrayList<RemoteViews> presentations = new ArrayList<>();
- parcel.readParcelableList(presentations, null);
- @SuppressWarnings("unchecked")
- final ArrayList<Serializable> filters =
- (ArrayList<Serializable>) parcel.readSerializable();
- final int idCount = (ids != null) ? ids.size() : 0;
- final int valueCount = (values != null) ? values.size() : 0;
- for (int i = 0; i < idCount; i++) {
+ final ArrayList<RemoteViews> presentations =
+ parcel.createTypedArrayList(RemoteViews.CREATOR);
+ final ArrayList<DatasetFieldFilter> filters =
+ parcel.createTypedArrayList(DatasetFieldFilter.CREATOR);
+ for (int i = 0; i < ids.size(); i++) {
final AutofillId id = ids.get(i);
- final AutofillValue value = (valueCount > i) ? values.get(i) : null;
- final RemoteViews fieldPresentation = presentations.isEmpty() ? null
- : presentations.get(i);
- final Pattern filter = (Pattern) filters.get(i);
+ final AutofillValue value = values.get(i);
+ final RemoteViews fieldPresentation = presentations.get(i);
+ final DatasetFieldFilter filter = filters.get(i);
builder.setLifeTheUniverseAndEverything(id, value, fieldPresentation, filter);
}
builder.setAuthentication(parcel.readParcelable(null));
@@ -521,4 +522,55 @@
return new Dataset[size];
}
};
+
+ /**
+ * Helper class used to indicate when the service explicitly set a {@link Pattern} filter for a
+ * dataset field‐ we cannot use a {@link Pattern} directly because then we wouldn't be
+ * able to differentiate whether the service explicitly passed a {@code null} filter to disable
+ * filter, or when it called the methods that does not take a filter {@link Pattern}.
+ *
+ * @hide
+ */
+ public static final class DatasetFieldFilter implements Parcelable {
+
+ @Nullable
+ public final Pattern pattern;
+
+ private DatasetFieldFilter(@Nullable Pattern pattern) {
+ this.pattern = pattern;
+ }
+
+ @Override
+ public String toString() {
+ if (!sDebug) return super.toString();
+
+ // Cannot log pattern because it could contain PII
+ return pattern == null ? "null" : pattern.pattern().length() + "_chars";
+ }
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @Override
+ public void writeToParcel(Parcel parcel, int flags) {
+ parcel.writeSerializable(pattern);
+ }
+
+ @SuppressWarnings("hiding")
+ public static final Creator<DatasetFieldFilter> CREATOR =
+ new Creator<DatasetFieldFilter>() {
+
+ @Override
+ public DatasetFieldFilter createFromParcel(Parcel parcel) {
+ return new DatasetFieldFilter((Pattern) parcel.readSerializable());
+ }
+
+ @Override
+ public DatasetFieldFilter[] newArray(int size) {
+ return new DatasetFieldFilter[size];
+ }
+ };
+ }
}
diff --git a/core/java/android/util/FeatureFlagUtils.java b/core/java/android/util/FeatureFlagUtils.java
index 57d23ce..410cdc6 100644
--- a/core/java/android/util/FeatureFlagUtils.java
+++ b/core/java/android/util/FeatureFlagUtils.java
@@ -42,7 +42,6 @@
DEFAULT_FLAGS.put("settings_battery_v2", "true");
DEFAULT_FLAGS.put("settings_battery_display_app_list", "false");
DEFAULT_FLAGS.put("settings_zone_picker_v2", "true");
- DEFAULT_FLAGS.put("settings_suggestion_ui_v2", "false");
DEFAULT_FLAGS.put("settings_about_phone_v2", "false");
DEFAULT_FLAGS.put("settings_bluetooth_while_driving", "false");
}
diff --git a/core/java/android/view/RenderNode.java b/core/java/android/view/RenderNode.java
index 5070151..ce7e8f3 100644
--- a/core/java/android/view/RenderNode.java
+++ b/core/java/android/view/RenderNode.java
@@ -353,9 +353,24 @@
return nHasShadow(mNativeRenderNode);
}
- /** setShadowColor */
- public boolean setShadowColor(int color) {
- return nSetShadowColor(mNativeRenderNode, color);
+ /** setSpotShadowColor */
+ public boolean setSpotShadowColor(int color) {
+ return nSetSpotShadowColor(mNativeRenderNode, color);
+ }
+
+ /** setAmbientShadowColor */
+ public boolean setAmbientShadowColor(int color) {
+ return nSetAmbientShadowColor(mNativeRenderNode, color);
+ }
+
+ /** getSpotShadowColor */
+ public int getSpotShadowColor() {
+ return nGetSpotShadowColor(mNativeRenderNode);
+ }
+
+ /** getAmbientShadowColor */
+ public int getAmbientShadowColor() {
+ return nGetAmbientShadowColor(mNativeRenderNode);
}
/**
@@ -915,7 +930,13 @@
@CriticalNative
private static native boolean nHasShadow(long renderNode);
@CriticalNative
- private static native boolean nSetShadowColor(long renderNode, int color);
+ private static native boolean nSetSpotShadowColor(long renderNode, int color);
+ @CriticalNative
+ private static native boolean nSetAmbientShadowColor(long renderNode, int color);
+ @CriticalNative
+ private static native int nGetSpotShadowColor(long renderNode);
+ @CriticalNative
+ private static native int nGetAmbientShadowColor(long renderNode);
@CriticalNative
private static native boolean nSetClipToOutline(long renderNode, boolean clipToOutline);
@CriticalNative
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index 5150c1f..3cbd275 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -17,7 +17,6 @@
package android.view;
import static android.view.accessibility.AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED;
-
import static java.lang.Math.max;
import android.animation.AnimatorInflater;
@@ -726,6 +725,8 @@
* @attr ref android.R.styleable#View_nextFocusRight
* @attr ref android.R.styleable#View_nextFocusUp
* @attr ref android.R.styleable#View_onClick
+ * @attr ref android.R.styleable#View_outlineSpotShadowColor
+ * @attr ref android.R.styleable#View_outlineAmbientShadowColor
* @attr ref android.R.styleable#View_padding
* @attr ref android.R.styleable#View_paddingHorizontal
* @attr ref android.R.styleable#View_paddingVertical
@@ -3975,6 +3976,7 @@
/**
* Current clip bounds. to which all drawing of this view are constrained.
*/
+ @ViewDebug.ExportedProperty(category = "drawing")
Rect mClipBounds = null;
private boolean mLastIsOpaque;
@@ -5446,6 +5448,12 @@
setAccessibilityPaneTitle(a.getString(attr));
}
break;
+ case R.styleable.View_outlineSpotShadowColor:
+ setOutlineSpotShadowColor(a.getColor(attr, Color.BLACK));
+ break;
+ case R.styleable.View_outlineAmbientShadowColor:
+ setOutlineAmbientShadowColor(a.getColor(attr, Color.BLACK));
+ break;
}
}
@@ -15481,14 +15489,61 @@
}
/**
- * @hide
+ * Sets the color of the spot shadow that is drawn when the view has a positive Z or
+ * elevation value.
+ * <p>
+ * By default the shadow color is black. Generally, this color will be opaque so the intensity
+ * of the shadow is consistent between different views with different colors.
+ * <p>
+ * The opacity of the final spot shadow is a function of the shadow caster height, the
+ * alpha channel of the outlineSpotShadowColor (typically opaque), and the
+ * {@link android.R.attr#spotShadowAlpha} theme attribute.
+ *
+ * @attr ref android.R.styleable#View_outlineSpotShadowColor
+ * @param color The color this View will cast for its elevation spot shadow.
*/
- public void setShadowColor(@ColorInt int color) {
- if (mRenderNode.setShadowColor(color)) {
+ public void setOutlineSpotShadowColor(@ColorInt int color) {
+ if (mRenderNode.setSpotShadowColor(color)) {
invalidateViewProperty(true, true);
}
}
+ /**
+ * @return The shadow color set by {@link #setOutlineSpotShadowColor(int)}, or black if nothing
+ * was set
+ */
+ public @ColorInt int getOutlineSpotShadowColor() {
+ return mRenderNode.getSpotShadowColor();
+ }
+
+ /**
+ * Sets the color of the ambient shadow that is drawn when the view has a positive Z or
+ * elevation value.
+ * <p>
+ * By default the shadow color is black. Generally, this color will be opaque so the intensity
+ * of the shadow is consistent between different views with different colors.
+ * <p>
+ * The opacity of the final ambient shadow is a function of the shadow caster height, the
+ * alpha channel of the outlineAmbientShadowColor (typically opaque), and the
+ * {@link android.R.attr#ambientShadowAlpha} theme attribute.
+ *
+ * @attr ref android.R.styleable#View_outlineAmbientShadowColor
+ * @param color The color this View will cast for its elevation shadow.
+ */
+ public void setOutlineAmbientShadowColor(@ColorInt int color) {
+ if (mRenderNode.setAmbientShadowColor(color)) {
+ invalidateViewProperty(true, true);
+ }
+ }
+
+ /**
+ * @return The shadow color set by {@link #setOutlineAmbientShadowColor(int)}, or black if
+ * nothing was set
+ */
+ public @ColorInt int getOutlineAmbientShadowColor() {
+ return mRenderNode.getAmbientShadowColor();
+ }
+
/** @hide */
public void setRevealClip(boolean shouldClip, float x, float y, float radius) {
@@ -26979,6 +27034,8 @@
stream.addProperty("drawing:scaleY", getScaleY());
stream.addProperty("drawing:pivotX", getPivotX());
stream.addProperty("drawing:pivotY", getPivotY());
+ stream.addProperty("drawing:clipBounds",
+ mClipBounds == null ? null : mClipBounds.toString());
stream.addProperty("drawing:opaque", isOpaque());
stream.addProperty("drawing:alpha", getAlpha());
stream.addProperty("drawing:transitionAlpha", getTransitionAlpha());
@@ -26990,6 +27047,8 @@
stream.addProperty("drawing:willNotCacheDrawing", willNotCacheDrawing());
stream.addProperty("drawing:drawingCacheEnabled", isDrawingCacheEnabled());
stream.addProperty("drawing:overlappingRendering", hasOverlappingRendering());
+ stream.addProperty("drawing:outlineAmbientShadowColor", getOutlineAmbientShadowColor());
+ stream.addProperty("drawing:outlineSpotShadowColor", getOutlineSpotShadowColor());
// focus
stream.addProperty("focus:hasFocus", hasFocus());
diff --git a/core/java/android/view/textclassifier/TextClassifierImpl.java b/core/java/android/view/textclassifier/TextClassifierImpl.java
index b03c70d..7c759e3 100644
--- a/core/java/android/view/textclassifier/TextClassifierImpl.java
+++ b/core/java/android/view/textclassifier/TextClassifierImpl.java
@@ -232,6 +232,7 @@
}
builder.addLink(span.getStartIndex(), span.getEndIndex(), entityScores);
}
+ return builder.build();
} catch (Throwable t) {
// Avoid throwing from this method. Log the error.
Log.e(LOG_TAG, "Error getting links info.", t);
diff --git a/core/java/android/view/textclassifier/TextLinks.java b/core/java/android/view/textclassifier/TextLinks.java
index 670efdd..ede5211 100644
--- a/core/java/android/view/textclassifier/TextLinks.java
+++ b/core/java/android/view/textclassifier/TextLinks.java
@@ -23,13 +23,13 @@
import android.os.LocaleList;
import android.os.Parcel;
import android.os.Parcelable;
-import android.widget.TextView;
import android.text.Spannable;
import android.text.style.ClickableSpan;
import android.text.util.Linkify;
import android.text.util.Linkify.LinkifyMask;
import android.view.View;
import android.view.textclassifier.TextClassifier.EntityType;
+import android.widget.TextView;
import com.android.internal.util.Preconditions;
@@ -351,7 +351,7 @@
* @throws IllegalArgumentException if applyStrategy is not valid
*
* @see #APPLY_STRATEGY_IGNORE
- * @see #APPLY_STRAGETY_REPLACE
+ * @see #APPLY_STRATEGY_REPLACE
*/
public Options setApplyStrategy(@ApplyStrategy int applyStrategy) {
checkValidApplyStrategy(applyStrategy);
@@ -391,8 +391,8 @@
* @return the strategy for resolving conflictswhen applying generated links to text that
* already have links.
*
- * @see #APPLY_STATEGY_IGNORE
- * @see #APPLY_STRAGETY_REPLACE
+ * @see #APPLY_STRATEGY_IGNORE
+ * @see #APPLY_STRATEGY_REPLACE
*/
@ApplyStrategy
public int getApplyStrategy() {
diff --git a/core/java/com/android/internal/statusbar/IStatusBar.aidl b/core/java/com/android/internal/statusbar/IStatusBar.aidl
index ebb5f9f..f70d3c2 100644
--- a/core/java/com/android/internal/statusbar/IStatusBar.aidl
+++ b/core/java/com/android/internal/statusbar/IStatusBar.aidl
@@ -132,6 +132,12 @@
void clickQsTile(in ComponentName tile);
void handleSystemKey(in int key);
+ /**
+ * Methods to show toast messages for screen pinning
+ */
+ void showPinningEnterExitToast(boolean entering);
+ void showPinningEscapeToast();
+
void showShutdownUi(boolean isReboot, String reason);
// Used to show the dialog when FingerprintService starts authentication
diff --git a/core/java/com/android/internal/statusbar/IStatusBarService.aidl b/core/java/com/android/internal/statusbar/IStatusBarService.aidl
index cb0b53c..adf4287 100644
--- a/core/java/com/android/internal/statusbar/IStatusBarService.aidl
+++ b/core/java/com/android/internal/statusbar/IStatusBarService.aidl
@@ -81,6 +81,12 @@
void clickTile(in ComponentName tile);
void handleSystemKey(in int key);
+ /**
+ * Methods to show toast messages for screen pinning
+ */
+ void showPinningEnterExitToast(boolean entering);
+ void showPinningEscapeToast();
+
// Used to show the dialog when FingerprintService starts authentication
void showFingerprintDialog(in Bundle bundle, IFingerprintDialogReceiver receiver);
// Used to hide the dialog when a finger is authenticated
diff --git a/core/java/com/android/internal/widget/LockPatternView.java b/core/java/com/android/internal/widget/LockPatternView.java
index 32a7a2d..7a248f2 100644
--- a/core/java/com/android/internal/widget/LockPatternView.java
+++ b/core/java/com/android/internal/widget/LockPatternView.java
@@ -118,6 +118,7 @@
private float mInProgressY = -1;
private long mAnimatingPeriodStart;
+ private long[] mLineFadeStart = new long[9];
private DisplayMode mPatternDisplayMode = DisplayMode.Correct;
private boolean mInputEnabled = true;
@@ -596,12 +597,14 @@
}
/**
- * Clear the pattern lookup table.
+ * Clear the pattern lookup table. Also reset the line fade start times for
+ * the next attempt.
*/
private void clearPatternDrawLookup() {
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 3; j++) {
mPatternDrawLookup[i][j] = false;
+ mLineFadeStart[i+j] = 0;
}
}
}
@@ -1136,7 +1139,8 @@
boolean anyCircles = false;
float lastX = 0f;
float lastY = 0f;
- for (int i = 0; i < count; i++) {
+ long elapsedRealtime = SystemClock.elapsedRealtime();
+ for (int i = 0; i < count; i++) {
Cell cell = pattern.get(i);
// only draw the part of the pattern stored in
@@ -1147,16 +1151,26 @@
}
anyCircles = true;
+ if (mLineFadeStart[i] == 0) {
+ mLineFadeStart[i] = SystemClock.elapsedRealtime();
+ }
+
float centerX = getCenterXForColumn(cell.column);
float centerY = getCenterYForRow(cell.row);
if (i != 0) {
+ // Set this line segment to slowly fade over the next second.
+ int lineFadeVal = (int) Math.min((elapsedRealtime -
+ mLineFadeStart[i])/2f, 255f);
+
CellState state = mCellStates[cell.row][cell.column];
currentPath.rewind();
currentPath.moveTo(lastX, lastY);
if (state.lineEndX != Float.MIN_VALUE && state.lineEndY != Float.MIN_VALUE) {
currentPath.lineTo(state.lineEndX, state.lineEndY);
+ mPathPaint.setAlpha((int) 255 - lineFadeVal );
} else {
currentPath.lineTo(centerX, centerY);
+ mPathPaint.setAlpha((int) 255 - lineFadeVal );
}
canvas.drawPath(currentPath, mPathPaint);
}
diff --git a/core/jni/Android.bp b/core/jni/Android.bp
index 93f95c6..33f80ce 100644
--- a/core/jni/Android.bp
+++ b/core/jni/Android.bp
@@ -164,6 +164,7 @@
"android_media_DeviceCallback.cpp",
"android_media_JetPlayer.cpp",
"android_media_MediaMetricsJNI.cpp",
+ "android_media_MicrophoneInfo.cpp",
"android_media_RemoteDisplay.cpp",
"android_media_ToneGenerator.cpp",
"android_hardware_Camera.cpp",
diff --git a/core/jni/AndroidRuntime.cpp b/core/jni/AndroidRuntime.cpp
index bf7a7794..f3c3c47 100644
--- a/core/jni/AndroidRuntime.cpp
+++ b/core/jni/AndroidRuntime.cpp
@@ -104,6 +104,7 @@
extern int register_android_media_AudioRecord(JNIEnv *env);
extern int register_android_media_AudioSystem(JNIEnv *env);
extern int register_android_media_AudioTrack(JNIEnv *env);
+extern int register_android_media_MicrophoneInfo(JNIEnv *env);
extern int register_android_media_JetPlayer(JNIEnv *env);
extern int register_android_media_ToneGenerator(JNIEnv *env);
@@ -1461,6 +1462,7 @@
REG_JNI(register_android_media_AudioSystem),
REG_JNI(register_android_media_AudioTrack),
REG_JNI(register_android_media_JetPlayer),
+ REG_JNI(register_android_media_MicrophoneInfo),
REG_JNI(register_android_media_RemoteDisplay),
REG_JNI(register_android_media_ToneGenerator),
diff --git a/core/jni/android_media_AudioRecord.cpp b/core/jni/android_media_AudioRecord.cpp
index ebd16c7..375d68b 100644
--- a/core/jni/android_media_AudioRecord.cpp
+++ b/core/jni/android_media_AudioRecord.cpp
@@ -25,6 +25,8 @@
#include <utils/Log.h>
#include <media/AudioRecord.h>
+#include <media/MicrophoneInfo.h>
+#include <vector>
#include <nativehelper/ScopedUtfChars.h>
@@ -32,6 +34,7 @@
#include "android_media_AudioErrors.h"
#include "android_media_DeviceCallback.h"
#include "android_media_MediaMetricsJNI.h"
+#include "android_media_MicrophoneInfo.h"
// ----------------------------------------------------------------------------
@@ -41,6 +44,11 @@
static const char* const kClassPathName = "android/media/AudioRecord";
static const char* const kAudioAttributesClassPathName = "android/media/AudioAttributes";
+static jclass gArrayListClass;
+static struct {
+ jmethodID add;
+} gArrayListMethods;
+
struct audio_record_fields_t {
// these fields provide access from C++ to the...
jmethodID postNativeEventInJava; //... event post callback method
@@ -785,6 +793,46 @@
}
// ----------------------------------------------------------------------------
+static jint android_media_AudioRecord_get_active_microphones(JNIEnv *env,
+ jobject thiz, jobject jActiveMicrophones) {
+ if (jActiveMicrophones == NULL) {
+ ALOGE("jActiveMicrophones is null");
+ return (jint)AUDIO_JAVA_BAD_VALUE;
+ }
+ if (!env->IsInstanceOf(jActiveMicrophones, gArrayListClass)) {
+ ALOGE("getActiveMicrophones not an arraylist");
+ return (jint)AUDIO_JAVA_BAD_VALUE;
+ }
+
+ sp<AudioRecord> lpRecorder = getAudioRecord(env, thiz);
+ if (lpRecorder == NULL) {
+ jniThrowException(env, "java/lang/IllegalStateException",
+ "Unable to retrieve AudioRecord pointer for getActiveMicrophones()");
+ return (jint)AUDIO_JAVA_ERROR;
+ }
+
+ jint jStatus = AUDIO_JAVA_SUCCESS;
+ std::vector<media::MicrophoneInfo> activeMicrophones;
+ status_t status = lpRecorder->getActiveMicrophones(&activeMicrophones);
+ if (status != NO_ERROR) {
+ ALOGE_IF(status != NO_ERROR, "AudioRecord::getActiveMicrophones error %d", status);
+ jStatus = nativeToJavaStatus(status);
+ return jStatus;
+ }
+
+ for (size_t i = 0; i < activeMicrophones.size(); i++) {
+ jobject jMicrophoneInfo;
+ jStatus = convertMicrophoneInfoFromNative(env, &jMicrophoneInfo, &activeMicrophones[i]);
+ if (jStatus != AUDIO_JAVA_SUCCESS) {
+ return jStatus;
+ }
+ env->CallBooleanMethod(jActiveMicrophones, gArrayListMethods.add, jMicrophoneInfo);
+ env->DeleteLocalRef(jMicrophoneInfo);
+ }
+ return jStatus;
+}
+
+// ----------------------------------------------------------------------------
// ----------------------------------------------------------------------------
static const JNINativeMethod gMethods[] = {
// name, signature, funcPtr
@@ -824,6 +872,8 @@
(void *)android_media_AudioRecord_disableDeviceCallback},
{"native_get_timestamp", "(Landroid/media/AudioTimestamp;I)I",
(void *)android_media_AudioRecord_get_timestamp},
+ {"native_get_active_microphones", "(Ljava/util/ArrayList;)I",
+ (void *)android_media_AudioRecord_get_active_microphones},
};
// field names found in android/media/AudioRecord.java
@@ -873,6 +923,10 @@
javaAudioTimestampFields.fieldNanoTime =
GetFieldIDOrDie(env, audioTimestampClass, "nanoTime", "J");
+ jclass arrayListClass = FindClassOrDie(env, "java/util/ArrayList");
+ gArrayListClass = MakeGlobalRefOrDie(env, arrayListClass);
+ gArrayListMethods.add = GetMethodIDOrDie(env, arrayListClass, "add", "(Ljava/lang/Object;)Z");
+
return RegisterMethodsOrDie(env, kClassPathName, gMethods, NELEM(gMethods));
}
diff --git a/core/jni/android_media_AudioSystem.cpp b/core/jni/android_media_AudioSystem.cpp
index 376a797..adaff1f 100644
--- a/core/jni/android_media_AudioSystem.cpp
+++ b/core/jni/android_media_AudioSystem.cpp
@@ -21,17 +21,20 @@
#include <utils/Log.h>
#include <sstream>
+#include <vector>
#include <jni.h>
#include <nativehelper/JNIHelp.h>
#include "core_jni_helpers.h"
#include <media/AudioSystem.h>
#include <media/AudioPolicy.h>
+#include <media/MicrophoneInfo.h>
#include <nativehelper/ScopedLocalRef.h>
#include <system/audio.h>
#include <system/audio_policy.h>
#include "android_media_AudioFormat.h"
#include "android_media_AudioErrors.h"
+#include "android_media_MicrophoneInfo.h"
// ----------------------------------------------------------------------------
@@ -143,7 +146,6 @@
jfieldID mSource;
} gAudioAttributesFields;
-
static const char* const kEventHandlerClassPathName =
"android/media/AudioPortEventHandler";
static struct {
@@ -1158,7 +1160,6 @@
return jStatus;
}
-
static jint
android_media_AudioSystem_listAudioPorts(JNIEnv *env, jobject clazz,
jobject jPorts, jintArray jGeneration)
@@ -1789,6 +1790,45 @@
return AudioSystem::isOffloadSupported(format);
}
+static jint
+android_media_AudioSystem_getMicrophones(JNIEnv *env, jobject thiz, jobject jMicrophonesInfo)
+{
+ ALOGV("getMicrophones");
+
+ if (jMicrophonesInfo == NULL) {
+ ALOGE("jMicrophonesInfo NULL MicrophoneInfo ArrayList");
+ return (jint)AUDIO_JAVA_BAD_VALUE;
+ }
+ if (!env->IsInstanceOf(jMicrophonesInfo, gArrayListClass)) {
+ ALOGE("getMicrophones not an arraylist");
+ return (jint)AUDIO_JAVA_BAD_VALUE;
+ }
+
+ jint jStatus;
+ std::vector<media::MicrophoneInfo> microphones;
+ status_t status = AudioSystem::getMicrophones(µphones);
+ if (status != NO_ERROR) {
+ ALOGE_IF(status != NO_ERROR, "AudioSystem::getMicrophones error %d", status);
+ jStatus = nativeToJavaStatus(status);
+ return jStatus;
+ }
+ if (microphones.size() == 0) {
+ jStatus = (jint)AUDIO_JAVA_SUCCESS;
+ return jStatus;
+ }
+ for (size_t i = 0; i < microphones.size(); i++) {
+ jobject jMicrophoneInfo;
+ jStatus = convertMicrophoneInfoFromNative(env, &jMicrophoneInfo, µphones[i]);
+ if (jStatus != AUDIO_JAVA_SUCCESS) {
+ return jStatus;
+ }
+ env->CallBooleanMethod(jMicrophonesInfo, gArrayListMethods.add, jMicrophoneInfo);
+ env->DeleteLocalRef(jMicrophoneInfo);
+ }
+
+ return jStatus;
+}
+
// ----------------------------------------------------------------------------
static const JNINativeMethod gMethods[] = {
@@ -1843,6 +1883,7 @@
{"systemReady", "()I", (void *)android_media_AudioSystem_systemReady},
{"getStreamVolumeDB", "(III)F", (void *)android_media_AudioSystem_getStreamVolumeDB},
{"native_is_offload_supported", "(IIII)Z", (void *)android_media_AudioSystem_isOffloadSupported},
+ {"getMicrophones", "(Ljava/util/ArrayList;)I", (void *)android_media_AudioSystem_getMicrophones},
};
diff --git a/core/jni/android_media_MicrophoneInfo.cpp b/core/jni/android_media_MicrophoneInfo.cpp
new file mode 100644
index 0000000..9198cbe
--- /dev/null
+++ b/core/jni/android_media_MicrophoneInfo.cpp
@@ -0,0 +1,187 @@
+/*
+ * Copyright (C) 2018 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.
+ */
+
+#include "android_media_MicrophoneInfo.h"
+#include "android_media_AudioErrors.h"
+#include "core_jni_helpers.h"
+
+using namespace android;
+
+static jclass gArrayListClass;
+static jmethodID gArrayListCstor;
+static struct {
+ jmethodID add;
+} gArrayListMethods;
+
+static jclass gFloatClass;
+static jmethodID gFloatCstor;
+
+static jclass gFloatArrayClass;
+
+static jclass gIntegerClass;
+static jmethodID gIntegerCstor;
+
+static jclass gMicrophoneInfoClass;
+static jmethodID gMicrophoneInfoCstor;
+
+static jclass gMicrophoneInfoCoordinateClass;
+static jmethodID gMicrophoneInfoCoordinateCstor;
+
+static jclass gPairClass;
+static jmethodID gPairCstor;
+
+namespace android {
+
+jint convertMicrophoneInfoFromNative(JNIEnv *env, jobject *jMicrophoneInfo,
+ const media::MicrophoneInfo *microphoneInfo)
+{
+ jint jStatus = (jint)AUDIO_JAVA_SUCCESS;
+ jstring jDeviceId = NULL;
+ jstring jAddress = NULL;
+ jobject jGeometricLocation = NULL;
+ jobject jOrientation = NULL;
+ jobject jFrequencyResponses = NULL;
+ jobject jChannelMappings = NULL;
+
+ jDeviceId = env->NewStringUTF(String8(microphoneInfo->getDeviceId()).string());
+ jAddress = env->NewStringUTF(String8(microphoneInfo->getAddress()).string());
+ if (microphoneInfo->getGeometricLocation().size() != 3 ||
+ microphoneInfo->getOrientation().size() != 3) {
+ jStatus = nativeToJavaStatus(BAD_VALUE);
+ goto exit;
+ }
+ jGeometricLocation = env->NewObject(gMicrophoneInfoCoordinateClass,
+ gMicrophoneInfoCoordinateCstor,
+ NULL,
+ microphoneInfo->getGeometricLocation()[0],
+ microphoneInfo->getGeometricLocation()[1],
+ microphoneInfo->getGeometricLocation()[2]);
+ jOrientation = env->NewObject(gMicrophoneInfoCoordinateClass,
+ gMicrophoneInfoCoordinateCstor,
+ NULL,
+ microphoneInfo->getOrientation()[0],
+ microphoneInfo->getOrientation()[1],
+ microphoneInfo->getOrientation()[2]);
+ // Create a list of Pair for frequency response.
+ if (microphoneInfo->getFrequencyResponses().size() != 2 ||
+ microphoneInfo->getFrequencyResponses()[0].size() !=
+ microphoneInfo->getFrequencyResponses()[1].size()) {
+ jStatus = nativeToJavaStatus(BAD_VALUE);
+ goto exit;
+ }
+ jFrequencyResponses = env->NewObject(gArrayListClass, gArrayListCstor);
+ for (size_t i = 0; i < microphoneInfo->getFrequencyResponses()[0].size(); i++) {
+ jobject jFrequency = env->NewObject(gFloatClass, gFloatCstor,
+ microphoneInfo->getFrequencyResponses()[0][i]);
+ jobject jResponse = env->NewObject(gFloatClass, gFloatCstor,
+ microphoneInfo->getFrequencyResponses()[1][i]);
+ jobject jFrequencyResponse = env->NewObject(gPairClass, gPairCstor, jFrequency, jResponse);
+ env->CallBooleanMethod(jFrequencyResponses, gArrayListMethods.add, jFrequencyResponse);
+ env->DeleteLocalRef(jFrequency);
+ env->DeleteLocalRef(jResponse);
+ env->DeleteLocalRef(jFrequencyResponse);
+ }
+ // Create a list of Pair for channel mapping.
+ if (microphoneInfo->getChannelMapping().size() != AUDIO_CHANNEL_COUNT_MAX) {
+ jStatus = nativeToJavaStatus(BAD_VALUE);
+ goto exit;
+ }
+ jChannelMappings = env->NewObject(gArrayListClass, gArrayListCstor);
+ for (size_t i = 0; i < microphoneInfo->getChannelMapping().size(); i++) {
+ int channelMappingType = microphoneInfo->getChannelMapping()[i];
+ if (channelMappingType != AUDIO_MICROPHONE_CHANNEL_MAPPING_UNUSED) {
+ jobject jChannelIndex = env->NewObject(gIntegerClass, gIntegerCstor, i);
+ jobject jChannelMappingType = env->NewObject(gIntegerClass, gIntegerCstor,
+ channelMappingType);
+ jobject jChannelMapping = env->NewObject(gPairClass, gPairCstor,
+ jChannelIndex, jChannelMappingType);
+ env->CallBooleanMethod(jChannelMappings, gArrayListMethods.add, jChannelMapping);
+ env->DeleteLocalRef(jChannelIndex);
+ env->DeleteLocalRef(jChannelMappingType);
+ env->DeleteLocalRef(jChannelMapping);
+ }
+ }
+ *jMicrophoneInfo = env->NewObject(gMicrophoneInfoClass, gMicrophoneInfoCstor, jDeviceId,
+ microphoneInfo->getType(), jAddress,
+ microphoneInfo->getDeviceLocation(),
+ microphoneInfo->getDeviceGroup(),
+ microphoneInfo->getIndexInTheGroup(),
+ jGeometricLocation, jOrientation,
+ jFrequencyResponses, jChannelMappings,
+ microphoneInfo->getSensitivity(),
+ microphoneInfo->getMaxSpl(),
+ microphoneInfo->getMinSpl(),
+ microphoneInfo->getDirectionality());
+
+exit:
+ if (jDeviceId != NULL) {
+ env->DeleteLocalRef(jDeviceId);
+ }
+ if (jAddress != NULL) {
+ env->DeleteLocalRef(jAddress);
+ }
+ if (jFrequencyResponses != NULL) {
+ env->DeleteLocalRef(jFrequencyResponses);
+ }
+ if (jChannelMappings != NULL) {
+ env->DeleteLocalRef(jChannelMappings);
+ }
+ if (jGeometricLocation != NULL) {
+ env->DeleteLocalRef(jGeometricLocation);
+ }
+ if (jOrientation != NULL) {
+ env->DeleteLocalRef(jOrientation);
+ }
+ return jStatus;
+}
+
+}
+
+int register_android_media_MicrophoneInfo(JNIEnv *env)
+{
+ jclass arrayListClass = FindClassOrDie(env, "java/util/ArrayList");
+ gArrayListClass = MakeGlobalRefOrDie(env, arrayListClass);
+ gArrayListCstor = GetMethodIDOrDie(env, arrayListClass, "<init>", "()V");
+ gArrayListMethods.add = GetMethodIDOrDie(env, arrayListClass, "add", "(Ljava/lang/Object;)Z");
+
+ jclass floatClass = FindClassOrDie(env, "java/lang/Float");
+ gFloatClass = MakeGlobalRefOrDie(env, floatClass);
+ gFloatCstor = GetMethodIDOrDie(env, floatClass, "<init>", "(F)V");
+
+ jclass floatArrayClass = FindClassOrDie(env, "[F");
+ gFloatArrayClass = MakeGlobalRefOrDie(env, floatArrayClass);
+
+ jclass integerClass = FindClassOrDie(env, "java/lang/Integer");
+ gIntegerClass = MakeGlobalRefOrDie(env, integerClass);
+ gIntegerCstor = GetMethodIDOrDie(env, integerClass, "<init>", "(I)V");
+
+ jclass microphoneInfoClass = FindClassOrDie(env, "android/media/MicrophoneInfo");
+ gMicrophoneInfoClass = MakeGlobalRefOrDie(env, microphoneInfoClass);
+ gMicrophoneInfoCstor = GetMethodIDOrDie(env, microphoneInfoClass, "<init>",
+ "(Ljava/lang/String;ILjava/lang/String;IIILandroid/media/MicrophoneInfo$Coordinate3F;Landroid/media/MicrophoneInfo$Coordinate3F;Ljava/util/List;Ljava/util/List;FFFI)V");
+
+ jclass microphoneInfoCoordinateClass = FindClassOrDie(
+ env, "android/media/MicrophoneInfo$Coordinate3F");
+ gMicrophoneInfoCoordinateClass = MakeGlobalRefOrDie(env, microphoneInfoCoordinateClass);
+ gMicrophoneInfoCoordinateCstor = GetMethodIDOrDie(env, microphoneInfoCoordinateClass, "<init>",
+ "(Landroid/media/MicrophoneInfo;FFF)V");
+
+ jclass pairClass = FindClassOrDie(env, "android/util/Pair");
+ gPairClass = MakeGlobalRefOrDie(env, pairClass);
+ gPairCstor = GetMethodIDOrDie(env, pairClass, "<init>", "(Ljava/lang/Object;Ljava/lang/Object;)V");
+
+ return 0;
+}
diff --git a/core/jni/android_media_MicrophoneInfo.h b/core/jni/android_media_MicrophoneInfo.h
new file mode 100644
index 0000000..241b6d0
--- /dev/null
+++ b/core/jni/android_media_MicrophoneInfo.h
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2018 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.
+ */
+
+#ifndef ANDROID_MEDIA_MICROPHONEINFO_H
+#define ANDROID_MEDIA_MICROPHONEINFO_H
+
+#include <system/audio.h>
+#include <media/MicrophoneInfo.h>
+
+#include "jni.h"
+
+namespace android {
+
+// Conversion from C++ MicrophoneInfo object to Java MicrophoneInfo object
+
+extern jint convertMicrophoneInfoFromNative(JNIEnv *env, jobject *jMicrophoneInfo,
+ const media::MicrophoneInfo *microphoneInfo);
+} // namespace android
+
+#endif
\ No newline at end of file
diff --git a/core/jni/android_view_RenderNode.cpp b/core/jni/android_view_RenderNode.cpp
index 37ff8c8..8770d78 100644
--- a/core/jni/android_view_RenderNode.cpp
+++ b/core/jni/android_view_RenderNode.cpp
@@ -174,8 +174,25 @@
return renderNode->stagingProperties().hasShadow();
}
-static jboolean android_view_RenderNode_setShadowColor(jlong renderNodePtr, jint shadowColor) {
- return SET_AND_DIRTY(setShadowColor, static_cast<SkColor>(shadowColor), RenderNode::GENERIC);
+static jboolean android_view_RenderNode_setSpotShadowColor(jlong renderNodePtr, jint shadowColor) {
+ return SET_AND_DIRTY(setSpotShadowColor,
+ static_cast<SkColor>(shadowColor), RenderNode::GENERIC);
+}
+
+static jint android_view_RenderNode_getSpotShadowColor(jlong renderNodePtr) {
+ RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr);
+ return renderNode->stagingProperties().getSpotShadowColor();
+}
+
+static jboolean android_view_RenderNode_setAmbientShadowColor(jlong renderNodePtr,
+ jint shadowColor) {
+ return SET_AND_DIRTY(setAmbientShadowColor,
+ static_cast<SkColor>(shadowColor), RenderNode::GENERIC);
+}
+
+static jint android_view_RenderNode_getAmbientShadowColor(jlong renderNodePtr) {
+ RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr);
+ return renderNode->stagingProperties().getAmbientShadowColor();
}
static jboolean android_view_RenderNode_setClipToOutline(jlong renderNodePtr,
@@ -575,7 +592,10 @@
{ "nSetOutlineEmpty", "(J)Z", (void*) android_view_RenderNode_setOutlineEmpty },
{ "nSetOutlineNone", "(J)Z", (void*) android_view_RenderNode_setOutlineNone },
{ "nHasShadow", "(J)Z", (void*) android_view_RenderNode_hasShadow },
- { "nSetShadowColor", "(JI)Z", (void*) android_view_RenderNode_setShadowColor },
+ { "nSetSpotShadowColor", "(JI)Z", (void*) android_view_RenderNode_setSpotShadowColor },
+ { "nGetSpotShadowColor", "(J)I", (void*) android_view_RenderNode_getSpotShadowColor },
+ { "nSetAmbientShadowColor","(JI)Z", (void*) android_view_RenderNode_setAmbientShadowColor },
+ { "nGetAmbientShadowColor","(J)I", (void*) android_view_RenderNode_getAmbientShadowColor },
{ "nSetClipToOutline", "(JZ)Z", (void*) android_view_RenderNode_setClipToOutline },
{ "nSetRevealClip", "(JZFFF)Z", (void*) android_view_RenderNode_setRevealClip },
diff --git a/core/res/res/layout/popup_menu_item_layout.xml b/core/res/res/layout/popup_menu_item_layout.xml
index 3b89f0d..1be915e 100644
--- a/core/res/res/layout/popup_menu_item_layout.xml
+++ b/core/res/res/layout/popup_menu_item_layout.xml
@@ -28,18 +28,18 @@
android:layout_marginBottom="4dip"
android:background="@drawable/list_divider_material" />
- <!-- Icon will be inserted here. -->
-
- <!-- The title and summary have some gap between them,
- and this 'group' should be centered vertically. -->
<LinearLayout
android:id="@+id/content"
- android:layout_width="wrap_content"
+ android:layout_width="match_parent"
android:layout_height="?attr/dropdownListPreferredItemHeight"
android:paddingEnd="16dip"
android:duplicateParentState="true" >
- <LinearLayout
+ <!-- Icon will be inserted here. -->
+
+ <!-- The title and summary have some gap between them,
+ and this 'group' should be centered vertically. -->
+ <RelativeLayout
android:layout_width="0dip"
android:layout_weight="1"
android:layout_height="wrap_content"
@@ -71,7 +71,7 @@
android:duplicateParentState="true"
android:textAlignment="viewStart" />
- </LinearLayout>
+ </RelativeLayout>
<ImageView
android:id="@+id/submenuarrow"
@@ -81,8 +81,9 @@
android:layout_marginStart="8dp"
android:scaleType="center"
android:visibility="gone" />
- </LinearLayout>
- <!-- Checkbox, and/or radio button will be inserted here. -->
+ <!-- Checkbox, and/or radio button will be inserted here. -->
+
+ </LinearLayout>
</com.android.internal.view.menu.ListMenuItemView>
diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml
index 0543305..68dad87 100644
--- a/core/res/res/values/attrs.xml
+++ b/core/res/res/values/attrs.xml
@@ -3036,6 +3036,28 @@
<!-- The title this view should present to accessibility as a pane title.
See {@link android.view.View#setAccessibilityPaneTitle(CharSequence)} -->
<attr name="accessibilityPaneTitle" format="string" />
+
+ <!-- Sets the color of the spot shadow that is drawn when the view has a positive Z or
+ elevation value.
+ <p>
+ By default the shadow color is black. Generally, this color will be opaque so the
+ intensity of the shadow is consistent between different views with different colors.
+ <p>
+ The opacity of the final spot shadow is a function of the shadow caster height, the
+ alpha channel of the outlineSpotShadowColor (typically opaque), and the
+ {@link android.R.attr#spotShadowAlpha} theme attribute. -->
+ <attr name="outlineSpotShadowColor" format="color" />
+
+ <!-- Sets the color of the ambient shadow that is drawn when the view has a positive Z
+ or elevation value.
+ <p>
+ By default the shadow color is black. Generally, this color will be opaque so the
+ intensity of the shadow is consistent between different views with different colors.
+ <p>
+ The opacity of the final ambient shadow is a function of the shadow caster height,
+ the alpha channel of the outlineAmbientShadowColor (typically opaque), and the
+ {@link android.R.attr#ambientShadowAlpha} theme attribute. -->
+ <attr name="outlineAmbientShadowColor" format="color" />
</declare-styleable>
<!-- Attributes that can be assigned to a tag for a particular View. -->
diff --git a/core/res/res/values/public.xml b/core/res/res/values/public.xml
index 30586d1..dee880f 100644
--- a/core/res/res/values/public.xml
+++ b/core/res/res/values/public.xml
@@ -2866,6 +2866,8 @@
<public name="lastBaselineToBottomHeight" />
<public name="lineHeight" />
<public name="accessibilityHeading" />
+ <public name="outlineSpotShadowColor" />
+ <public name="outlineAmbientShadowColor" />
</public-group>
<public-group type="style" first-id="0x010302e0">
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index 3cde765..3b752c4 100644
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -3222,19 +3222,23 @@
<string name="dlg_ok">OK</string>
<!-- USB_PREFERENCES: Notification for when the user connected to the charger only. This is the title -->
- <string name="usb_charging_notification_title">USB charging this device</string>
+ <string name="usb_charging_notification_title">Charging this device via USB</string>
<!-- USB_PREFERENCES: Notification for when the user connects the phone to supply power to attached device. This is the title -->
- <string name="usb_supplying_notification_title">USB supplying power to attached device</string>
+ <string name="usb_supplying_notification_title">Charging connected device via USB</string>
<!-- USB_PREFERENCES: Notification for when the user connects the phone to a computer via USB in MTP mode. This is the title -->
- <string name="usb_mtp_notification_title">USB for file transfer</string>
+ <string name="usb_mtp_notification_title">USB file transfer turned on</string>
<!-- USB_PREFERENCES: Notification for when the user connects the phone to a computer via USB in PTP mode. This is the title -->
- <string name="usb_ptp_notification_title">USB for photo transfer</string>
+ <string name="usb_ptp_notification_title">PTP via USB turned on</string>
+ <!-- USB_PREFERENCES: Notification for when the user connects the phone to a computer via USB in Tethering mode. This is the title -->
+ <string name="usb_tether_notification_title">USB tethering turned on</string>
<!-- USB_PREFERENCES: Notification for when the user connects the phone to a computer via USB in MIDI mode. This is the title -->
- <string name="usb_midi_notification_title">USB for MIDI</string>
+ <string name="usb_midi_notification_title">MIDI via USB turned on</string>
<!-- USB_PREFERENCES: Notification for when a USB accessory is attached. This is the title -->
- <string name="usb_accessory_notification_title">Connected to a USB accessory</string>
+ <string name="usb_accessory_notification_title">USB accessory mode turned on</string>
<!-- See USB_PREFERENCES. This is the message. -->
<string name="usb_notification_message">Tap for more options.</string>
+ <!-- See USB_PREFERENCES. This is the message when a data mode is turned on (mtp, ptp, midi) and the device is supplying power.. -->
+ <string name="usb_power_notification_message">Charging connected device. Tap for more options.</string>
<!-- USB_PREFERENCES: Notification for when a type-c USB audio accessory is attached but not supported. This is the title -->
<string name="usb_unsupported_audio_accessory_title">Analog audio accessory detected</string>
<!-- Message of notification shown when a type-c USB audio accessory is attached but not supported. -->
@@ -4419,15 +4423,6 @@
<!-- DO NOT TRANSLATE -->
<string name="date_picker_day_typeface">sans-serif-medium</string>
- <!-- Notify use that they are in Lock-to-app -->
- <string name="lock_to_app_toast">To unpin this screen, touch & hold Back and Overview
- buttons</string>
-
- <!-- Starting lock-to-app indication. -->
- <string name="lock_to_app_start">Screen pinned</string>
- <!-- Exting lock-to-app indication. -->
- <string name="lock_to_app_exit">Screen unpinned</string>
-
<!-- Lock-to-app unlock pin string -->
<string name="lock_to_app_unlock_pin">Ask for PIN before unpinning</string>
<!-- Lock-to-app unlock pattern string -->
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index a62d49e..fee5a80 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -767,9 +767,6 @@
<java-symbol type="string" name="kilobyteShort" />
<java-symbol type="string" name="last_month" />
<java-symbol type="string" name="launchBrowserDefault" />
- <java-symbol type="string" name="lock_to_app_toast" />
- <java-symbol type="string" name="lock_to_app_start" />
- <java-symbol type="string" name="lock_to_app_exit" />
<java-symbol type="string" name="lock_to_app_unlock_pin" />
<java-symbol type="string" name="lock_to_app_unlock_pattern" />
<java-symbol type="string" name="lock_to_app_unlock_password" />
@@ -2026,8 +2023,10 @@
<java-symbol type="string" name="usb_mtp_notification_title" />
<java-symbol type="string" name="usb_charging_notification_title" />
<java-symbol type="string" name="usb_notification_message" />
+ <java-symbol type="string" name="usb_power_notification_message" />
<java-symbol type="string" name="usb_ptp_notification_title" />
<java-symbol type="string" name="usb_midi_notification_title" />
+ <java-symbol type="string" name="usb_tether_notification_title" />
<java-symbol type="string" name="usb_supplying_notification_title" />
<java-symbol type="string" name="usb_unsupported_audio_accessory_title" />
<java-symbol type="string" name="usb_unsupported_audio_accessory_message" />
diff --git a/keystore/java/android/security/keystore/AndroidKeyStoreKeyGeneratorSpi.java b/keystore/java/android/security/keystore/AndroidKeyStoreKeyGeneratorSpi.java
index f721ed3..09b3b9b 100644
--- a/keystore/java/android/security/keystore/AndroidKeyStoreKeyGeneratorSpi.java
+++ b/keystore/java/android/security/keystore/AndroidKeyStoreKeyGeneratorSpi.java
@@ -248,7 +248,8 @@
spec.getUserAuthenticationValidityDurationSeconds(),
spec.isUserAuthenticationValidWhileOnBody(),
spec.isInvalidatedByBiometricEnrollment(),
- GateKeeper.INVALID_SECURE_USER_ID /* boundToSpecificSecureUserId */);
+ GateKeeper.INVALID_SECURE_USER_ID /* boundToSpecificSecureUserId */,
+ spec.isUserConfirmationRequired());
} catch (IllegalStateException | IllegalArgumentException e) {
throw new InvalidAlgorithmParameterException(e);
}
@@ -289,7 +290,8 @@
spec.getUserAuthenticationValidityDurationSeconds(),
spec.isUserAuthenticationValidWhileOnBody(),
spec.isInvalidatedByBiometricEnrollment(),
- GateKeeper.INVALID_SECURE_USER_ID /* boundToSpecificSecureUserId */);
+ GateKeeper.INVALID_SECURE_USER_ID /* boundToSpecificSecureUserId */,
+ spec.isUserConfirmationRequired());
if (spec.isTrustedUserPresenceRequired()) {
args.addBoolean(KeymasterDefs.KM_TAG_TRUSTED_USER_PRESENCE_REQUIRED);
}
diff --git a/keystore/java/android/security/keystore/AndroidKeyStoreKeyPairGeneratorSpi.java b/keystore/java/android/security/keystore/AndroidKeyStoreKeyPairGeneratorSpi.java
index d1eb688..e33e3cd 100644
--- a/keystore/java/android/security/keystore/AndroidKeyStoreKeyPairGeneratorSpi.java
+++ b/keystore/java/android/security/keystore/AndroidKeyStoreKeyPairGeneratorSpi.java
@@ -349,7 +349,8 @@
mSpec.getUserAuthenticationValidityDurationSeconds(),
mSpec.isUserAuthenticationValidWhileOnBody(),
mSpec.isInvalidatedByBiometricEnrollment(),
- GateKeeper.INVALID_SECURE_USER_ID /* boundToSpecificSecureUserId */);
+ GateKeeper.INVALID_SECURE_USER_ID /* boundToSpecificSecureUserId */,
+ mSpec.isUserConfirmationRequired());
} catch (IllegalArgumentException | IllegalStateException e) {
throw new InvalidAlgorithmParameterException(e);
}
@@ -545,7 +546,8 @@
mSpec.getUserAuthenticationValidityDurationSeconds(),
mSpec.isUserAuthenticationValidWhileOnBody(),
mSpec.isInvalidatedByBiometricEnrollment(),
- GateKeeper.INVALID_SECURE_USER_ID /* boundToSpecificSecureUserId */);
+ GateKeeper.INVALID_SECURE_USER_ID /* boundToSpecificSecureUserId */,
+ mSpec.isUserConfirmationRequired());
args.addDateIfNotNull(KeymasterDefs.KM_TAG_ACTIVE_DATETIME, mSpec.getKeyValidityStart());
args.addDateIfNotNull(KeymasterDefs.KM_TAG_ORIGINATION_EXPIRE_DATETIME,
mSpec.getKeyValidityForOriginationEnd());
diff --git a/keystore/java/android/security/keystore/AndroidKeyStoreSecretKeyFactorySpi.java b/keystore/java/android/security/keystore/AndroidKeyStoreSecretKeyFactorySpi.java
index 9df37f5..7bbc099 100644
--- a/keystore/java/android/security/keystore/AndroidKeyStoreSecretKeyFactorySpi.java
+++ b/keystore/java/android/security/keystore/AndroidKeyStoreSecretKeyFactorySpi.java
@@ -190,6 +190,8 @@
&& !keymasterSecureUserIds.contains(getGateKeeperSecureUserId());
}
+ boolean userConfirmationRequired = keyCharacteristics.hwEnforced.getBoolean(KeymasterDefs.KM_TAG_TRUSTED_CONFIRMATION_REQUIRED);
+
return new KeyInfo(entryAlias,
insideSecureHardware,
origin,
@@ -207,7 +209,8 @@
userAuthenticationRequirementEnforcedBySecureHardware,
userAuthenticationValidWhileOnBody,
trustedUserPresenceRequred,
- invalidatedByBiometricEnrollment);
+ invalidatedByBiometricEnrollment,
+ userConfirmationRequired);
}
private static BigInteger getGateKeeperSecureUserId() throws ProviderException {
diff --git a/keystore/java/android/security/keystore/AndroidKeyStoreSpi.java b/keystore/java/android/security/keystore/AndroidKeyStoreSpi.java
index 440e086..05cc74a 100644
--- a/keystore/java/android/security/keystore/AndroidKeyStoreSpi.java
+++ b/keystore/java/android/security/keystore/AndroidKeyStoreSpi.java
@@ -502,7 +502,8 @@
spec.getUserAuthenticationValidityDurationSeconds(),
spec.isUserAuthenticationValidWhileOnBody(),
spec.isInvalidatedByBiometricEnrollment(),
- spec.getBoundToSpecificSecureUserId());
+ spec.getBoundToSpecificSecureUserId(),
+ spec.isUserConfirmationRequired());
importArgs.addDateIfNotNull(KeymasterDefs.KM_TAG_ACTIVE_DATETIME,
spec.getKeyValidityStart());
importArgs.addDateIfNotNull(KeymasterDefs.KM_TAG_ORIGINATION_EXPIRE_DATETIME,
@@ -704,7 +705,8 @@
params.getUserAuthenticationValidityDurationSeconds(),
params.isUserAuthenticationValidWhileOnBody(),
params.isInvalidatedByBiometricEnrollment(),
- params.getBoundToSpecificSecureUserId());
+ params.getBoundToSpecificSecureUserId(),
+ params.isUserConfirmationRequired());
KeymasterUtils.addMinMacLengthAuthorizationIfNecessary(
args,
keymasterAlgorithm,
diff --git a/keystore/java/android/security/keystore/KeyGenParameterSpec.java b/keystore/java/android/security/keystore/KeyGenParameterSpec.java
index a896c72..da23c70 100644
--- a/keystore/java/android/security/keystore/KeyGenParameterSpec.java
+++ b/keystore/java/android/security/keystore/KeyGenParameterSpec.java
@@ -264,6 +264,7 @@
private final boolean mUserAuthenticationValidWhileOnBody;
private final boolean mInvalidatedByBiometricEnrollment;
private final boolean mIsStrongBoxBacked;
+ private final boolean mUserConfirmationRequired;
/**
* @hide should be built with Builder
@@ -293,7 +294,8 @@
boolean uniqueIdIncluded,
boolean userAuthenticationValidWhileOnBody,
boolean invalidatedByBiometricEnrollment,
- boolean isStrongBoxBacked) {
+ boolean isStrongBoxBacked,
+ boolean userConfirmationRequired) {
if (TextUtils.isEmpty(keyStoreAlias)) {
throw new IllegalArgumentException("keyStoreAlias must not be empty");
}
@@ -341,6 +343,7 @@
mUserAuthenticationValidWhileOnBody = userAuthenticationValidWhileOnBody;
mInvalidatedByBiometricEnrollment = invalidatedByBiometricEnrollment;
mIsStrongBoxBacked = isStrongBoxBacked;
+ mUserConfirmationRequired = userConfirmationRequired;
}
/**
@@ -547,6 +550,26 @@
}
/**
+ * Returns {@code true} if the key is authorized to be used only for messages confirmed by the
+ * user.
+ *
+ * Confirmation is separate from user authentication (see
+ * {@link Builder#setUserAuthenticationRequired(boolean)}). Keys can be created that require
+ * confirmation but not user authentication, or user authentication but not confirmation, or
+ * both. Confirmation verifies that some user with physical possession of the device has
+ * approved a displayed message. User authentication verifies that the correct user is present
+ * and has authenticated.
+ *
+ * <p>This authorization applies only to secret key and private key operations. Public key
+ * operations are not restricted.
+ *
+ * @see Builder#setUserConfirmationRequired(boolean)
+ */
+ public boolean isUserConfirmationRequired() {
+ return mUserConfirmationRequired;
+ }
+
+ /**
* Gets the duration of time (seconds) for which this key is authorized to be used after the
* user is successfully authenticated. This has effect only if user authentication is required
* (see {@link #isUserAuthenticationRequired()}).
@@ -675,6 +698,7 @@
private boolean mUserAuthenticationValidWhileOnBody;
private boolean mInvalidatedByBiometricEnrollment = true;
private boolean mIsStrongBoxBacked = false;
+ private boolean mUserConfirmationRequired;
/**
* Creates a new instance of the {@code Builder}.
@@ -1063,6 +1087,29 @@
}
/**
+ * Sets whether this key is authorized to be used only for messages confirmed by the
+ * user.
+ *
+ * Confirmation is separate from user authentication (see
+ * {@link #setUserAuthenticationRequired(boolean)}). Keys can be created that require
+ * confirmation but not user authentication, or user authentication but not confirmation,
+ * or both. Confirmation verifies that some user with physical possession of the device has
+ * approved a displayed message. User authentication verifies that the correct user is
+ * present and has authenticated.
+ *
+ * <p>This authorization applies only to secret key and private key operations. Public key
+ * operations are not restricted.
+ *
+ * @see {@link android.security.ConfirmationPrompter ConfirmationPrompter} class for
+ * more details about user confirmations.
+ */
+ @NonNull
+ public Builder setUserConfirmationRequired(boolean required) {
+ mUserConfirmationRequired = required;
+ return this;
+ }
+
+ /**
* Sets the duration of time (seconds) for which this key is authorized to be used after the
* user is successfully authenticated. This has effect if the key requires user
* authentication for its use (see {@link #setUserAuthenticationRequired(boolean)}).
@@ -1249,7 +1296,8 @@
mUniqueIdIncluded,
mUserAuthenticationValidWhileOnBody,
mInvalidatedByBiometricEnrollment,
- mIsStrongBoxBacked);
+ mIsStrongBoxBacked,
+ mUserConfirmationRequired);
}
}
}
diff --git a/keystore/java/android/security/keystore/KeyInfo.java b/keystore/java/android/security/keystore/KeyInfo.java
index 864f62a..0a75cd5 100644
--- a/keystore/java/android/security/keystore/KeyInfo.java
+++ b/keystore/java/android/security/keystore/KeyInfo.java
@@ -82,6 +82,7 @@
private final boolean mUserAuthenticationValidWhileOnBody;
private final boolean mTrustedUserPresenceRequired;
private final boolean mInvalidatedByBiometricEnrollment;
+ private final boolean mUserConfirmationRequired;
/**
* @hide
@@ -103,7 +104,8 @@
boolean userAuthenticationRequirementEnforcedBySecureHardware,
boolean userAuthenticationValidWhileOnBody,
boolean trustedUserPresenceRequired,
- boolean invalidatedByBiometricEnrollment) {
+ boolean invalidatedByBiometricEnrollment,
+ boolean userConfirmationRequired) {
mKeystoreAlias = keystoreKeyAlias;
mInsideSecureHardware = insideSecureHardware;
mOrigin = origin;
@@ -125,6 +127,7 @@
mUserAuthenticationValidWhileOnBody = userAuthenticationValidWhileOnBody;
mTrustedUserPresenceRequired = trustedUserPresenceRequired;
mInvalidatedByBiometricEnrollment = invalidatedByBiometricEnrollment;
+ mUserConfirmationRequired = userConfirmationRequired;
}
/**
@@ -260,6 +263,27 @@
}
/**
+ * Returns {@code true} if the key is authorized to be used only for messages confirmed by the
+ * user.
+ *
+ * Confirmation is separate from user authentication (see
+ * {@link #isUserAuthenticationRequired()}). Keys can be created that require confirmation but
+ * not user authentication, or user authentication but not confirmation, or both. Confirmation
+ * verifies that some user with physical possession of the device has approved a displayed
+ * message. User authentication verifies that the correct user is present and has
+ * authenticated.
+ *
+ * <p>This authorization applies only to secret key and private key operations. Public key
+ * operations are not restricted.
+ *
+ * @see KeyGenParameterSpec.Builder#setUserConfirmationRequired(boolean)
+ * @see KeyProtection.Builder#setUserConfirmationRequired(boolean)
+ */
+ public boolean isUserConfirmationRequired() {
+ return mUserConfirmationRequired;
+ }
+
+ /**
* Gets the duration of time (seconds) for which this key is authorized to be used after the
* user is successfully authenticated. This has effect only if user authentication is required
* (see {@link #isUserAuthenticationRequired()}).
diff --git a/keystore/java/android/security/keystore/KeyProtection.java b/keystore/java/android/security/keystore/KeyProtection.java
index dbacb9c..b5b3281 100644
--- a/keystore/java/android/security/keystore/KeyProtection.java
+++ b/keystore/java/android/security/keystore/KeyProtection.java
@@ -228,6 +228,7 @@
private final boolean mInvalidatedByBiometricEnrollment;
private final long mBoundToSecureUserId;
private final boolean mCriticalToDeviceEncryption;
+ private final boolean mUserConfirmationRequired;
private KeyProtection(
Date keyValidityStart,
@@ -244,7 +245,8 @@
boolean userAuthenticationValidWhileOnBody,
boolean invalidatedByBiometricEnrollment,
long boundToSecureUserId,
- boolean criticalToDeviceEncryption) {
+ boolean criticalToDeviceEncryption,
+ boolean userConfirmationRequired) {
mKeyValidityStart = Utils.cloneIfNotNull(keyValidityStart);
mKeyValidityForOriginationEnd = Utils.cloneIfNotNull(keyValidityForOriginationEnd);
mKeyValidityForConsumptionEnd = Utils.cloneIfNotNull(keyValidityForConsumptionEnd);
@@ -262,6 +264,7 @@
mInvalidatedByBiometricEnrollment = invalidatedByBiometricEnrollment;
mBoundToSecureUserId = boundToSecureUserId;
mCriticalToDeviceEncryption = criticalToDeviceEncryption;
+ mUserConfirmationRequired = userConfirmationRequired;
}
/**
@@ -396,6 +399,26 @@
}
/**
+ * Returns {@code true} if the key is authorized to be used only for messages confirmed by the
+ * user.
+ *
+ * Confirmation is separate from user authentication (see
+ * {@link #isUserAuthenticationRequired()}). Keys can be created that require confirmation but
+ * not user authentication, or user authentication but not confirmation, or both. Confirmation
+ * verifies that some user with physical possession of the device has approved a displayed
+ * message. User authentication verifies that the correct user is present and has
+ * authenticated.
+ *
+ * <p>This authorization applies only to secret key and private key operations. Public key
+ * operations are not restricted.
+ *
+ * @see Builder#setUserConfirmationRequired(boolean)
+ */
+ public boolean isUserConfirmationRequired() {
+ return mUserConfirmationRequired;
+ }
+
+ /**
* Gets the duration of time (seconds) for which this key is authorized to be used after the
* user is successfully authenticated. This has effect only if user authentication is required
* (see {@link #isUserAuthenticationRequired()}).
@@ -488,6 +511,7 @@
private int mUserAuthenticationValidityDurationSeconds = -1;
private boolean mUserAuthenticationValidWhileOnBody;
private boolean mInvalidatedByBiometricEnrollment = true;
+ private boolean mUserConfirmationRequired;
private long mBoundToSecureUserId = GateKeeper.INVALID_SECURE_USER_ID;
private boolean mCriticalToDeviceEncryption = false;
@@ -719,6 +743,29 @@
}
/**
+ * Sets whether this key is authorized to be used only for messages confirmed by the
+ * user.
+ *
+ * Confirmation is separate from user authentication (see
+ * {@link #setUserAuthenticationRequired(boolean)}). Keys can be created that require
+ * confirmation but not user authentication, or user authentication but not confirmation,
+ * or both. Confirmation verifies that some user with physical possession of the device has
+ * approved a displayed message. User authentication verifies that the correct user is
+ * present and has authenticated.
+ *
+ * <p>This authorization applies only to secret key and private key operations. Public key
+ * operations are not restricted.
+ *
+ * @see {@link android.security.ConfirmationPrompter ConfirmationPrompter} class for
+ * more details about user confirmations.
+ */
+ @NonNull
+ public Builder setUserConfirmationRequired(boolean required) {
+ mUserConfirmationRequired = required;
+ return this;
+ }
+
+ /**
* Sets the duration of time (seconds) for which this key is authorized to be used after the
* user is successfully authenticated. This has effect if the key requires user
* authentication for its use (see {@link #setUserAuthenticationRequired(boolean)}).
@@ -866,7 +913,8 @@
mUserAuthenticationValidWhileOnBody,
mInvalidatedByBiometricEnrollment,
mBoundToSecureUserId,
- mCriticalToDeviceEncryption);
+ mCriticalToDeviceEncryption,
+ mUserConfirmationRequired);
}
}
}
diff --git a/keystore/java/android/security/keystore/KeymasterUtils.java b/keystore/java/android/security/keystore/KeymasterUtils.java
index 34c8d1f..4e28601 100644
--- a/keystore/java/android/security/keystore/KeymasterUtils.java
+++ b/keystore/java/android/security/keystore/KeymasterUtils.java
@@ -16,6 +16,7 @@
package android.security.keystore;
+import android.util.Log;
import android.hardware.fingerprint.FingerprintManager;
import android.security.GateKeeper;
import android.security.KeyStore;
@@ -93,6 +94,8 @@
* overriding the default logic in this method where the key is bound to either the root
* SID of the current user, or the fingerprint SID if explicit fingerprint authorization
* is requested.
+ * @param userConfirmationRequired whether user confirmation is required to authorize the use
+ * of the key.
* @throws IllegalStateException if user authentication is required but the system is in a wrong
* state (e.g., secure lock screen not set up) for generating or importing keys that
* require user authentication.
@@ -102,7 +105,12 @@
int userAuthenticationValidityDurationSeconds,
boolean userAuthenticationValidWhileOnBody,
boolean invalidatedByBiometricEnrollment,
- long boundToSpecificSecureUserId) {
+ long boundToSpecificSecureUserId,
+ boolean userConfirmationRequired) {
+ if (userConfirmationRequired) {
+ args.addBoolean(KeymasterDefs.KM_TAG_TRUSTED_CONFIRMATION_REQUIRED);
+ }
+
if (!userAuthenticationRequired) {
args.addBoolean(KeymasterDefs.KM_TAG_NO_AUTH_REQUIRED);
return;
diff --git a/libs/hwui/RenderProperties.h b/libs/hwui/RenderProperties.h
index 3d2c252..55f4d89 100644
--- a/libs/hwui/RenderProperties.h
+++ b/libs/hwui/RenderProperties.h
@@ -507,12 +507,20 @@
getOutline().getAlpha() != 0.0f;
}
- SkColor getShadowColor() const {
- return mPrimitiveFields.mShadowColor;
+ SkColor getSpotShadowColor() const {
+ return mPrimitiveFields.mSpotShadowColor;
}
- bool setShadowColor(SkColor shadowColor) {
- return RP_SET(mPrimitiveFields.mShadowColor, shadowColor);
+ bool setSpotShadowColor(SkColor shadowColor) {
+ return RP_SET(mPrimitiveFields.mSpotShadowColor, shadowColor);
+ }
+
+ SkColor getAmbientShadowColor() const {
+ return mPrimitiveFields.mAmbientShadowColor;
+ }
+
+ bool setAmbientShadowColor(SkColor shadowColor) {
+ return RP_SET(mPrimitiveFields.mAmbientShadowColor, shadowColor);
}
bool fitsOnLayer() const {
@@ -538,7 +546,8 @@
int mLeft = 0, mTop = 0, mRight = 0, mBottom = 0;
int mWidth = 0, mHeight = 0;
int mClippingFlags = CLIP_TO_BOUNDS;
- SkColor mShadowColor = SK_ColorBLACK;
+ SkColor mSpotShadowColor = SK_ColorBLACK;
+ SkColor mAmbientShadowColor = SK_ColorBLACK;
float mAlpha = 1;
float mTranslationX = 0, mTranslationY = 0, mTranslationZ = 0;
float mElevation = 0;
diff --git a/libs/hwui/pipeline/skia/ReorderBarrierDrawables.cpp b/libs/hwui/pipeline/skia/ReorderBarrierDrawables.cpp
index 7b59ccf..25c51f2 100644
--- a/libs/hwui/pipeline/skia/ReorderBarrierDrawables.cpp
+++ b/libs/hwui/pipeline/skia/ReorderBarrierDrawables.cpp
@@ -111,6 +111,10 @@
}
}
+static SkColor multiplyAlpha(SkColor color, float alpha) {
+ return SkColorSetA(color, alpha * SkColorGetA(color));
+}
+
// copied from FrameBuilder::deferShadow
void EndReorderBarrierDrawable::drawShadow(SkCanvas* canvas, RenderNodeDrawable* caster) {
const RenderProperties& casterProperties = caster->getNodeProperties();
@@ -187,9 +191,11 @@
} else {
zParams = SkPoint3::Make(0, 0, casterProperties.getZ());
}
+ SkColor ambientColor = multiplyAlpha(casterProperties.getAmbientShadowColor(), ambientAlpha);
+ SkColor spotColor = multiplyAlpha(casterProperties.getSpotShadowColor(), spotAlpha);
SkShadowUtils::DrawShadow(
canvas, *casterPath, zParams, skiaLightPos, SkiaPipeline::getLightRadius(),
- ambientAlpha, spotAlpha, casterProperties.getShadowColor(),
+ ambientColor, spotColor,
casterAlpha < 1.0f ? SkShadowFlags::kTransparentOccluder_ShadowFlag : 0);
}
diff --git a/media/java/android/media/AudioManager.java b/media/java/android/media/AudioManager.java
index 22fa620..bf51d97 100644
--- a/media/java/android/media/AudioManager.java
+++ b/media/java/android/media/AudioManager.java
@@ -48,11 +48,13 @@
import android.os.SystemClock;
import android.os.UserHandle;
import android.provider.Settings;
+import android.text.TextUtils;
import android.util.ArrayMap;
import android.util.Log;
import android.util.Slog;
import android.view.KeyEvent;
+import java.io.IOException;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.util.ArrayList;
@@ -4578,6 +4580,51 @@
}
}
+ /**
+ * Set port id for microphones by matching device type and address.
+ * @hide
+ */
+ public static void setPortIdForMicrophones(ArrayList<MicrophoneInfo> microphones) {
+ AudioDeviceInfo[] devices = getDevicesStatic(AudioManager.GET_DEVICES_INPUTS);
+ for (int i = microphones.size() - 1; i >= 0; i--) {
+ boolean foundPortId = false;
+ for (AudioDeviceInfo device : devices) {
+ if (device.getPort().type() == microphones.get(i).getInternalDeviceType()
+ && TextUtils.equals(device.getAddress(), microphones.get(i).getAddress())) {
+ microphones.get(i).setId(device.getId());
+ foundPortId = true;
+ break;
+ }
+ }
+ if (!foundPortId) {
+ Log.i(TAG, "Failed to find port id for device with type:"
+ + microphones.get(i).getType() + " address:"
+ + microphones.get(i).getAddress());
+ microphones.remove(i);
+ }
+ }
+ }
+
+ /**
+ * Returns a list of {@link MicrophoneInfo} that corresponds to the characteristics
+ * of all available microphones. The list is empty when no microphones are available
+ * on the device. An error during the query will result in an IOException being thrown.
+ *
+ * @return a list that contains all microphones' characteristics
+ * @throws IOException if an error occurs.
+ */
+ public List<MicrophoneInfo> getMicrophones() throws IOException {
+ ArrayList<MicrophoneInfo> microphones = new ArrayList<MicrophoneInfo>();
+ int status = AudioSystem.getMicrophones(microphones);
+ if (status != AudioManager.SUCCESS) {
+ // fail and bail!
+ Log.e(TAG, "getMicrophones failed:" + status);
+ return new ArrayList<MicrophoneInfo>(); // Always return a list.
+ }
+ setPortIdForMicrophones(microphones);
+ return microphones;
+ }
+
// Since we need to calculate the changes since THE LAST NOTIFICATION, and not since the
// (unpredictable) last time updateAudioPortCache() was called by someone, keep a list
// of the ports that exist at the time of the last notification.
diff --git a/media/java/android/media/AudioRecord.java b/media/java/android/media/AudioRecord.java
index eb6e830..d0963cb 100644
--- a/media/java/android/media/AudioRecord.java
+++ b/media/java/android/media/AudioRecord.java
@@ -16,12 +16,15 @@
package android.media;
+import java.io.IOException;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.ref.WeakReference;
import java.nio.ByteBuffer;
import java.util.Collection;
import java.util.Iterator;
+import java.util.ArrayList;
+import java.util.List;
import android.annotation.IntDef;
import android.annotation.NonNull;
@@ -35,6 +38,7 @@
import android.os.PersistableBundle;
import android.os.RemoteException;
import android.os.ServiceManager;
+import android.text.TextUtils;
import android.util.ArrayMap;
import android.util.Log;
@@ -1601,6 +1605,32 @@
}
}
+ //--------------------------------------------------------------------------
+ // Microphone information
+ //--------------------
+ /**
+ * Returns a lists of {@link MicrophoneInfo} representing the active microphones.
+ * By querying channel mapping for each active microphone, developer can know how
+ * the microphone is used by each channels or a capture stream.
+ * Note that the information about the active microphones may change during a recording.
+ * See {@link AudioManager#registerAudioDeviceCallback} to be notified of changes
+ * in the audio devices, querying the active microphones then will return the latest
+ * information.
+ *
+ * @return a lists of {@link MicrophoneInfo} representing the active microphones.
+ * @throws IOException if an error occurs
+ */
+ public List<MicrophoneInfo> getActiveMicrophones() throws IOException {
+ ArrayList<MicrophoneInfo> activeMicrophones = new ArrayList<>();
+ int status = native_get_active_microphones(activeMicrophones);
+ if (status != AudioManager.SUCCESS) {
+ Log.e(TAG, "getActiveMicrophones failed:" + status);
+ return new ArrayList<MicrophoneInfo>();
+ }
+ AudioManager.setPortIdForMicrophones(activeMicrophones);
+ return activeMicrophones;
+ }
+
//---------------------------------------------------------
// Interface definitions
//--------------------
@@ -1746,6 +1776,9 @@
private native final int native_get_timestamp(@NonNull AudioTimestamp outTimestamp,
@AudioTimestamp.Timebase int timebase);
+ private native final int native_get_active_microphones(
+ ArrayList<MicrophoneInfo> activeMicrophones);
+
//---------------------------------------------------------
// Utility methods
//------------------
diff --git a/media/java/android/media/AudioSystem.java b/media/java/android/media/AudioSystem.java
index dcd37da..be9fcb8 100644
--- a/media/java/android/media/AudioSystem.java
+++ b/media/java/android/media/AudioSystem.java
@@ -827,6 +827,8 @@
private static native boolean native_is_offload_supported(int encoding, int sampleRate,
int channelMask, int channelIndexMask);
+ public static native int getMicrophones(ArrayList<MicrophoneInfo> microphonesInfo);
+
// Items shared with audio service
/**
diff --git a/media/java/android/media/MicrophoneInfo.java b/media/java/android/media/MicrophoneInfo.java
new file mode 100644
index 0000000..21f9171
--- /dev/null
+++ b/media/java/android/media/MicrophoneInfo.java
@@ -0,0 +1,342 @@
+/*
+ * Copyright (C) 2018 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 android.media;
+
+import android.annotation.IntDef;
+import android.util.Pair;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.util.List;
+
+/**
+ * Class providing information on a microphone. It indicates the location and orientation of the
+ * microphone on the device as well as useful information like frequency response and sensitivity.
+ * It can be used by applications implementing special pre processing effects like noise suppression
+ * of beam forming that need to know about precise microphone characteristics in order to adapt
+ * their algorithms.
+ */
+public final class MicrophoneInfo {
+
+ /**
+ * A microphone that the location is unknown.
+ */
+ public static final int LOCATION_UNKNOWN = 0;
+
+ /**
+ * A microphone that locate on main body of the device.
+ */
+ public static final int LOCATION_MAINBODY = 1;
+
+ /**
+ * A microphone that locate on a movable main body of the device.
+ */
+ public static final int LOCATION_MAINBODY_MOVABLE = 2;
+
+ /**
+ * A microphone that locate on a peripheral.
+ */
+ public static final int LOCATION_PERIPHERAL = 3;
+
+ /**
+ * Unknown microphone directionality.
+ */
+ public static final int DIRECTIONALITY_UNKNOW = 0;
+
+ /**
+ * Microphone directionality type: omni.
+ */
+ public static final int DIRECTIONALITY_OMNI = 1;
+
+ /**
+ * Microphone directionality type: bi-directional.
+ */
+ public static final int DIRECTIONALITY_BI_DIRECTIONAL = 2;
+
+ /**
+ * Microphone directionality type: cardioid.
+ */
+ public static final int DIRECTIONALITY_CARDIOID = 3;
+
+ /**
+ * Microphone directionality type: hyper cardioid.
+ */
+ public static final int DIRECTIONALITY_HYPER_CARDIOID = 4;
+
+ /**
+ * Microphone directionality type: super cardioid.
+ */
+ public static final int DIRECTIONALITY_SUPER_CARDIOID = 5;
+
+ /**
+ * The channel contains raw audio from this microphone.
+ */
+ public static final int CHANNEL_MAPPING_DIRECT = 1;
+
+ /**
+ * The channel contains processed audio from this microphone and possibly another microphone.
+ */
+ public static final int CHANNEL_MAPPING_PROCESSED = 2;
+
+ /** @hide */
+ @IntDef(flag = true, prefix = { "LOCATION_" }, value = {
+ LOCATION_UNKNOWN,
+ LOCATION_MAINBODY,
+ LOCATION_MAINBODY_MOVABLE,
+ LOCATION_PERIPHERAL,
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface MicrophoneLocation {}
+
+ /** @hide */
+ @IntDef(flag = true, prefix = { "DIRECTIONALITY_" }, value = {
+ DIRECTIONALITY_UNKNOW,
+ DIRECTIONALITY_OMNI,
+ DIRECTIONALITY_BI_DIRECTIONAL,
+ DIRECTIONALITY_CARDIOID,
+ DIRECTIONALITY_HYPER_CARDIOID,
+ DIRECTIONALITY_SUPER_CARDIOID,
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface MicrophoneDirectionality {}
+
+ private Coordinate3F mPosition;
+ private Coordinate3F mOrientation;
+ private String mDeviceId;
+ private String mAddress;
+ private List<Pair<Float, Float>> mFrequencyResponse;
+ private List<Pair<Integer, Integer>> mChannelMapping;
+ private float mMaxSpl;
+ private float mMinSpl;
+ private float mSensitivity;
+ private int mLocation;
+ private int mGroup; /* Usually 0 will be used for main body. */
+ private int mIndexInTheGroup;
+ private int mPortId; /* mPortId will correspond to the id in AudioPort */
+ private int mType;
+ private int mDirectionality;
+
+ MicrophoneInfo(String deviceId, int type, String address, int location,
+ int group, int indexInTheGroup, Coordinate3F position,
+ Coordinate3F orientation, List<Pair<Float, Float>> frequencyResponse,
+ List<Pair<Integer, Integer>> channelMapping, float sensitivity, float maxSpl,
+ float minSpl, int directionality) {
+ mDeviceId = deviceId;
+ mType = type;
+ mAddress = address;
+ mLocation = location;
+ mGroup = group;
+ mIndexInTheGroup = indexInTheGroup;
+ mPosition = position;
+ mOrientation = orientation;
+ mFrequencyResponse = frequencyResponse;
+ mChannelMapping = channelMapping;
+ mSensitivity = sensitivity;
+ mMaxSpl = maxSpl;
+ mMinSpl = minSpl;
+ mDirectionality = directionality;
+ }
+
+ /**
+ * Returns alphanumeric code that uniquely identifies the device.
+ *
+ * @return the description of the microphone
+ */
+ public String getDescription() {
+ return mDeviceId;
+ }
+
+ /**
+ * Returns The system unique device ID that corresponds to the id
+ * returned by {@link AudioDeviceInfo#getId()}.
+ *
+ * @return the microphone's id
+ */
+ public int getId() {
+ return mPortId;
+ }
+
+ /**
+ * @hide
+ * Returns the internal device type (e.g AudioSystem.DEVICE_IN_BUILTIN_MIC).
+ * The internal device type could be used when getting microphone's port id
+ * by matching type and address.
+ *
+ * @return the internal device type
+ */
+ public int getInternalDeviceType() {
+ return mType;
+ }
+
+ /**
+ * Returns the device type identifier of the microphone (e.g AudioDeviceInfo.TYPE_BUILTIN_MIC).
+ *
+ * @return the device type of the microphone
+ */
+ public int getType() {
+ return AudioDeviceInfo.convertInternalDeviceToDeviceType(mType);
+ }
+
+ /**
+ * @hide
+ * Returns The "address" string of the microphone that corresponds to the
+ * address returned by {@link AudioDeviceInfo#getAddress()}
+ * @return the address of the microphone
+ */
+ public String getAddress() {
+ return mAddress;
+ }
+
+ /**
+ * Returns the location of the microphone. The return value is
+ * one of {@link #LOCATION_UNKNOWN}, {@link #LOCATION_MAINBODY},
+ * {@link #LOCATION_MAINBODY_MOVABLE}, or {@link #LOCATION_PERIPHERAL}.
+ *
+ * @return the location of the microphone
+ */
+ public @MicrophoneLocation int getLocation() {
+ return mLocation;
+ }
+
+ /**
+ * Returns A device group id that can be used to group together microphones on the same
+ * peripheral, attachments or logical groups. Main body is usually group 0.
+ *
+ * @return the group of the microphone
+ */
+ public int getGroup() {
+ return mGroup;
+ }
+
+ /**
+ * Returns unique index for device within its group.
+ *
+ * @return the microphone's index in its group
+ */
+ public int getIndexInTheGroup() {
+ return mIndexInTheGroup;
+ }
+
+ /**
+ * Returns A {@link Coordinate3F} object that represents the geometric location of microphone
+ * in meters, from botton-left-back corner of appliance. X-axis, Y-axis and Z-axis show
+ * as the x, y, z values.
+ *
+ * @return the geometric location of the microphone
+ */
+ public Coordinate3F getPosition() {
+ return mPosition;
+ }
+
+ /**
+ * Returns A {@link Coordinate3F} object that represents the orientation of microphone.
+ * X-axis, Y-axis and Z-axis show as the x, y, z value. The orientation will be normalized
+ * such as sqrt(x^2 + y^2 + z^2) equals 1.
+ *
+ * @return the orientation of the microphone
+ */
+ public Coordinate3F getOrientation() {
+ return mOrientation;
+ }
+
+ /**
+ * Returns a {@link android.util.Pair} list of frequency responses.
+ * For every {@link android.util.Pair} in the list, the first value represents frequency in Hz,
+ * and the second value represents response in dB.
+ *
+ * @return the frequency response of the microphone
+ */
+ public List<Pair<Float, Float>> getFrequencyResponse() {
+ return mFrequencyResponse;
+ }
+
+ /**
+ * Returns a {@link android.util.Pair} list for channel mapping, which indicating how this
+ * microphone is used by each channels or a capture stream. For each {@link android.util.Pair},
+ * the first value is channel index, the second value is channel mapping type, which could be
+ * either {@link #CHANNEL_MAPPING_DIRECT} or {@link #CHANNEL_MAPPING_PROCESSED}.
+ * If a channel has contributions from more than one microphone, it is likely the HAL
+ * did some extra processing to combine the sources, but this is to be inferred by the user.
+ * Empty list when the MicrophoneInfo is returned by AudioManager.getMicrophones().
+ * At least one entry when the MicrophoneInfo is returned by AudioRecord.getActiveMicrophones().
+ *
+ * @return a {@link android.util.Pair} list for channel mapping
+ */
+ public List<Pair<Integer, Integer>> getChannelMapping() {
+ return mChannelMapping;
+ }
+
+ /**
+ * Returns the level in dBFS produced by a 1000Hz tone at 94 dB SPL.
+ *
+ * @return the sensitivity of the microphone
+ */
+ public float getSensitivity() {
+ return mSensitivity;
+ }
+
+ /**
+ * Returns the level in dB of the maximum SPL supported by the device at 1000Hz.
+ *
+ * @return the maximum level in dB
+ */
+ public float getMaxSpl() {
+ return mMaxSpl;
+ }
+
+ /**
+ * Returns the level in dB of the minimum SPL that can be registered by the device at 1000Hz.
+ *
+ * @return the minimum level in dB
+ */
+ public float getMinSpl() {
+ return mMinSpl;
+ }
+
+ /**
+ * Returns the directionality of microphone. The return value is one of
+ * {@link #DIRECTIONALITY_UNKNOW}, {@link #DIRECTIONALITY_OMNI},
+ * {@link #DIRECTIONALITY_BI_DIRECTIONAL}, {@link #DIRECTIONALITY_CARDIOID},
+ * {@link #DIRECTIONALITY_HYPER_CARDIOID}, or {@link #DIRECTIONALITY_SUPER_CARDIOID}.
+ *
+ * @return the directionality of microphone
+ */
+ public @MicrophoneDirectionality int getDirectionality() {
+ return mDirectionality;
+ }
+
+ /**
+ * Set the port id for the device.
+ * @hide
+ */
+ public void setId(int portId) {
+ mPortId = portId;
+ }
+
+ /* A class containing three float value to represent a 3D coordinate */
+ public class Coordinate3F {
+ public final float x;
+ public final float y;
+ public final float z;
+
+ Coordinate3F(float x, float y, float z) {
+ this.x = x;
+ this.y = y;
+ this.z = z;
+ }
+ }
+}
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java b/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java
index 7428149..1dc8e46 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java
@@ -87,7 +87,6 @@
private static final HashSet<String> mValidTables = new HashSet<String>();
- private static final String DATABASE_JOURNAL_SUFFIX = "-journal";
private static final String DATABASE_BACKUP_SUFFIX = "-backup";
private static final String TABLE_SYSTEM = "system";
@@ -148,12 +147,7 @@
}
File databaseFile = mContext.getDatabasePath(getDatabaseName());
if (databaseFile.exists()) {
- databaseFile.delete();
- }
- File databaseJournalFile = mContext.getDatabasePath(getDatabaseName()
- + DATABASE_JOURNAL_SUFFIX);
- if (databaseJournalFile.exists()) {
- databaseJournalFile.delete();
+ SQLiteDatabase.deleteDatabase(databaseFile);
}
}
diff --git a/packages/SystemUI/res/drawable/qs_footer_drag_handle.xml b/packages/SystemUI/res/drawable/qs_footer_drag_handle.xml
new file mode 100644
index 0000000..509cd1f
--- /dev/null
+++ b/packages/SystemUI/res/drawable/qs_footer_drag_handle.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2018 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.
+-->
+<shape
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:shape="rectangle" >
+ <solid
+ android:color="#e5e5e5" />
+ <corners android:radius="2dp" />
+</shape>
diff --git a/packages/SystemUI/res/layout/qs_footer_impl.xml b/packages/SystemUI/res/layout/qs_footer_impl.xml
index 9f6a946..997fe6d 100644
--- a/packages/SystemUI/res/layout/qs_footer_impl.xml
+++ b/packages/SystemUI/res/layout/qs_footer_impl.xml
@@ -32,80 +32,108 @@
<LinearLayout
android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:layout_marginStart="16dp"
+ android:layout_height="match_parent"
+ android:layout_marginStart="8dp"
android:layout_marginEnd="8dp"
- android:gravity="end">
+ android:gravity="end" >
- <com.android.keyguard.CarrierText
- android:id="@+id/qs_carrier_text"
+ <LinearLayout
+ android:layout_width="0dp"
+ android:layout_height="match_parent"
+ android:layout_weight="1" >
+ <!-- Add an extra 8dp margin before carrier text without shifting it right -->
+ <android.widget.Space
+ android:layout_width="8dp"
+ android:layout_height="match_parent" />
+
+ <com.android.keyguard.CarrierText
+ android:id="@+id/qs_carrier_text"
+ android:layout_width="0dp"
+ android:layout_height="match_parent"
+ android:layout_weight="1"
+ android:gravity="center_vertical|start"
+ android:ellipsize="marquee"
+ android:textAppearance="?android:attr/textAppearanceSmall"
+ android:textColor="?android:attr/textColorPrimary"
+ android:textDirection="locale"
+ android:singleLine="true" />
+ </LinearLayout>
+
+ <FrameLayout
+ android:layout_width="24dp"
+ android:layout_height="match_parent" >
+ <View
+ android:id="@+id/qs_drag_handle_view"
+ android:layout_width="match_parent"
+ android:layout_height="4dp"
+ android:layout_marginTop="28dp"
+ android:background="@drawable/qs_footer_drag_handle" />
+ </FrameLayout>
+
+ <LinearLayout
+ android:id="@+id/qs_footer_actions_container"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
- android:gravity="center_vertical|start"
- android:ellipsize="marquee"
- android:textAppearance="?android:attr/textAppearanceSmall"
- android:textColor="?android:attr/textColorPrimary"
- android:textDirection="locale"
- android:singleLine="true" />
-
- <com.android.systemui.statusbar.phone.MultiUserSwitch
- android:id="@+id/multi_user_switch"
- android:layout_width="48dp"
- android:layout_height="48dp"
- android:layout_alignParentEnd="true"
- android:background="@drawable/ripple_drawable"
- android:focusable="true">
-
- <ImageView
- android:id="@+id/multi_user_avatar"
- android:layout_width="@dimen/multi_user_avatar_expanded_size"
- android:layout_height="@dimen/multi_user_avatar_expanded_size"
- android:layout_gravity="center"
- android:scaleType="centerInside"/>
- </com.android.systemui.statusbar.phone.MultiUserSwitch>
-
- <com.android.systemui.statusbar.AlphaOptimizedImageView
- android:id="@android:id/edit"
- android:layout_width="48dp"
- android:layout_height="48dp"
- android:background="?android:attr/selectableItemBackgroundBorderless"
- android:clickable="true"
- android:clipToPadding="false"
- android:contentDescription="@string/accessibility_quick_settings_edit"
- android:focusable="true"
- android:padding="16dp"
- android:src="@drawable/ic_mode_edit"
- android:tint="?android:attr/colorForeground"/>
-
- <com.android.systemui.statusbar.AlphaOptimizedFrameLayout
- android:id="@+id/settings_button_container"
- android:layout_width="48dp"
- android:layout_height="48dp"
- android:clipChildren="false"
- android:clipToPadding="false">
-
- <com.android.systemui.statusbar.phone.SettingsButton
- android:id="@+id/settings_button"
- style="@android:style/Widget.Material.Button.Borderless"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
+ android:gravity="end" >
+ <com.android.systemui.statusbar.phone.MultiUserSwitch
+ android:id="@+id/multi_user_switch"
+ android:layout_width="48dp"
+ android:layout_height="48dp"
+ android:layout_alignParentEnd="true"
android:background="@drawable/ripple_drawable"
- android:contentDescription="@string/accessibility_quick_settings_settings"
- android:src="@drawable/ic_settings_16dp"
- android:tint="?android:attr/colorForeground"/>
+ android:focusable="true">
+
+ <ImageView
+ android:id="@+id/multi_user_avatar"
+ android:layout_width="@dimen/multi_user_avatar_expanded_size"
+ android:layout_height="@dimen/multi_user_avatar_expanded_size"
+ android:layout_gravity="center"
+ android:scaleType="centerInside"/>
+ </com.android.systemui.statusbar.phone.MultiUserSwitch>
<com.android.systemui.statusbar.AlphaOptimizedImageView
- android:id="@+id/tuner_icon"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:paddingStart="36dp"
- android:paddingEnd="4dp"
- android:src="@drawable/tuner"
- android:tint="?android:attr/textColorTertiary"
- android:visibility="invisible"/>
+ android:id="@android:id/edit"
+ android:layout_width="48dp"
+ android:layout_height="48dp"
+ android:background="?android:attr/selectableItemBackgroundBorderless"
+ android:clickable="true"
+ android:clipToPadding="false"
+ android:contentDescription="@string/accessibility_quick_settings_edit"
+ android:focusable="true"
+ android:padding="16dp"
+ android:src="@drawable/ic_mode_edit"
+ android:tint="?android:attr/colorForeground"/>
- </com.android.systemui.statusbar.AlphaOptimizedFrameLayout>
+ <com.android.systemui.statusbar.AlphaOptimizedFrameLayout
+ android:id="@+id/settings_button_container"
+ android:layout_width="48dp"
+ android:layout_height="48dp"
+ android:clipChildren="false"
+ android:clipToPadding="false">
+
+ <com.android.systemui.statusbar.phone.SettingsButton
+ android:id="@+id/settings_button"
+ style="@android:style/Widget.Material.Button.Borderless"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:background="@drawable/ripple_drawable"
+ android:contentDescription="@string/accessibility_quick_settings_settings"
+ android:src="@drawable/ic_settings_16dp"
+ android:tint="?android:attr/colorForeground"/>
+
+ <com.android.systemui.statusbar.AlphaOptimizedImageView
+ android:id="@+id/tuner_icon"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:paddingStart="36dp"
+ android:paddingEnd="4dp"
+ android:src="@drawable/tuner"
+ android:tint="?android:attr/textColorTertiary"
+ android:visibility="invisible"/>
+
+ </com.android.systemui.statusbar.AlphaOptimizedFrameLayout>
+ </LinearLayout>
</LinearLayout>
</com.android.systemui.qs.QSFooterImpl>
diff --git a/packages/SystemUI/res/layout/screen_pinning_request_buttons.xml b/packages/SystemUI/res/layout/screen_pinning_request_buttons.xml
index c2b1009..a3118b0 100644
--- a/packages/SystemUI/res/layout/screen_pinning_request_buttons.xml
+++ b/packages/SystemUI/res/layout/screen_pinning_request_buttons.xml
@@ -84,7 +84,25 @@
android:layout_height="@dimen/screen_pinning_request_button_height"
android:layout_weight="0"
android:paddingStart="@dimen/screen_pinning_request_frame_padding"
- android:paddingEnd="@dimen/screen_pinning_request_frame_padding" >
+ android:paddingEnd="@dimen/screen_pinning_request_frame_padding"
+ android:theme="@*android:style/ThemeOverlay.DeviceDefault.Accent">
+
+ <ImageView
+ android:id="@+id/screen_pinning_home_bg_light"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:scaleType="matrix"
+ android:src="@drawable/screen_pinning_light_bg_circ" />
+
+ <ImageView
+ android:id="@+id/screen_pinning_home_bg"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:paddingEnd="@dimen/screen_pinning_request_inner_padding"
+ android:paddingStart="@dimen/screen_pinning_request_inner_padding"
+ android:paddingTop="@dimen/screen_pinning_request_inner_padding"
+ android:scaleType="matrix"
+ android:src="@drawable/screen_pinning_bg_circ" />
<ImageView
android:layout_width="match_parent"
diff --git a/packages/SystemUI/res/layout/volume_dialog.xml b/packages/SystemUI/res/layout/volume_dialog.xml
index 117cd14..53dff05 100644
--- a/packages/SystemUI/res/layout/volume_dialog.xml
+++ b/packages/SystemUI/res/layout/volume_dialog.xml
@@ -59,6 +59,7 @@
android:gravity="center"
android:layout_gravity="end"
android:translationZ="8dp"
+ android:clickable="true"
android:orientation="vertical" >
<TextView
@@ -76,7 +77,7 @@
android:id="@+id/ringer_icon"
style="@style/VolumeButtons"
android:background="?android:selectableItemBackgroundBorderless"
- android:layout_width="@dimen/volume_button_size"
+ android:layout_width="@dimen/volume_dialog_panel_width"
android:layout_height="@dimen/volume_button_size"
android:tint="?android:attr/colorAccent"
android:soundEffectsEnabled="false" />
diff --git a/packages/SystemUI/res/layout/volume_dialog_row.xml b/packages/SystemUI/res/layout/volume_dialog_row.xml
index 3e80085..a9e5adf 100644
--- a/packages/SystemUI/res/layout/volume_dialog_row.xml
+++ b/packages/SystemUI/res/layout/volume_dialog_row.xml
@@ -63,6 +63,7 @@
android:background="?android:selectableItemBackgroundBorderless"
android:contentDescription="@string/accessibility_output_chooser"
style="@style/VolumeButtons"
+ android:clickable="false"
android:layout_centerVertical="true"
android:src="@drawable/ic_swap"
android:soundEffectsEnabled="false" />
@@ -70,7 +71,7 @@
</LinearLayout>
<FrameLayout
android:id="@+id/volume_row_slider_frame"
- android:padding="10dp"
+ android:padding="0dp"
android:layout_width="@dimen/volume_dialog_panel_width"
android:layout_height="150dp">
<SeekBar
@@ -80,8 +81,6 @@
android:layout_width="150dp"
android:layout_height="@dimen/volume_dialog_panel_width"
android:layout_gravity="center"
- android:focusable="true"
- android:focusableInTouchMode="true"
android:rotation="270" />
</FrameLayout>
@@ -91,6 +90,7 @@
android:padding="10dp"
android:layout_width="@dimen/volume_button_size"
android:layout_height="@dimen/volume_button_size"
+ android:background="?android:selectableItemBackgroundBorderless"
android:soundEffectsEnabled="false" />
</LinearLayout>
\ No newline at end of file
diff --git a/packages/SystemUI/res/values/config.xml b/packages/SystemUI/res/values/config.xml
index 1cc1cc8..ae910fe 100644
--- a/packages/SystemUI/res/values/config.xml
+++ b/packages/SystemUI/res/values/config.xml
@@ -124,7 +124,7 @@
<!-- Tiles native to System UI. Order should match "quick_settings_tiles_default" -->
<string name="quick_settings_tiles_stock" translatable="false">
- wifi,cell,battery,dnd,flashlight,rotation,bt,airplane,location,hotspot,inversion,saver,work,cast,night
+ wifi,cell,battery,dnd,flashlight,rotation,bt,airplane,location,hotspot,inversion,saver,work,cast,night,alarm
</string>
<!-- The tiles to display in QuickSettings -->
diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml
index 72615ce..fadcbcd 100644
--- a/packages/SystemUI/res/values/strings.xml
+++ b/packages/SystemUI/res/values/strings.xml
@@ -739,6 +739,8 @@
<string name="quick_settings_wifi_on_label">Wi-Fi On</string>
<!-- QuickSettings: Wifi detail panel, text when there are no items [CHAR LIMIT=NONE] -->
<string name="quick_settings_wifi_detail_empty_text">No Wi-Fi networks available</string>
+ <!-- QuickSettings: Alarm title [CHAR LIMIT=NONE] -->
+ <string name="quick_settings_alarm_title">Alarm</string>
<!-- QuickSettings: Cast title [CHAR LIMIT=NONE] -->
<string name="quick_settings_cast_title">Cast</string>
<!-- QuickSettings: Cast detail panel, status text when casting [CHAR LIMIT=NONE] -->
@@ -1279,12 +1281,23 @@
<string name="screen_pinning_title">Screen is pinned</string>
<!-- Screen pinning dialog description. -->
<string name="screen_pinning_description">This keeps it in view until you unpin. Touch & hold Back and Overview to unpin.</string>
+ <string name="screen_pinning_description_recents_invisible">This keeps it in view until you unpin. Touch & hold Back and Home to unpin.</string>
<!-- Screen pinning dialog description. -->
<string name="screen_pinning_description_accessible">This keeps it in view until you unpin. Touch & hold Overview to unpin.</string>
+ <string name="screen_pinning_description_recents_invisible_accessible">This keeps it in view until you unpin. Touch & hold Home to unpin.</string>
+ <!-- Notify use that they are in Lock-to-app -->
+ <string name="screen_pinning_toast">To unpin this screen, touch & hold Back and Overview
+ buttons</string>
+ <string name="screen_pinning_toast_recents_invisible">To unpin this screen, touch & hold Back
+ and Home buttons</string>
<!-- Screen pinning positive response. -->
<string name="screen_pinning_positive">Got it</string>
<!-- Screen pinning negative response. -->
<string name="screen_pinning_negative">No thanks</string>
+ <!-- Enter/Exiting screen pinning indication. -->
+ <string name="screen_pinning_start">Screen pinned</string>
+ <string name="screen_pinning_exit">Screen unpinned</string>
+
<!-- Hide quick settings tile confirmation title -->
<string name="quick_settings_reset_confirmation_title">Hide <xliff:g id="tile_label" example="Hotspot">%1$s</xliff:g>?</string>
diff --git a/packages/SystemUI/src/com/android/systemui/SysUIToast.java b/packages/SystemUI/src/com/android/systemui/SysUIToast.java
index 89bc82f..43b918d 100644
--- a/packages/SystemUI/src/com/android/systemui/SysUIToast.java
+++ b/packages/SystemUI/src/com/android/systemui/SysUIToast.java
@@ -15,13 +15,19 @@
*/
package com.android.systemui;
+import android.annotation.StringRes;
import android.content.Context;
import android.view.WindowManager;
import android.widget.Toast;
+import static android.widget.Toast.Duration;
public class SysUIToast {
- public static Toast makeText(Context context, CharSequence text, int duration) {
+ public static Toast makeText(Context context, @StringRes int resId, @Duration int duration) {
+ return makeText(context, context.getString(resId), duration);
+ }
+
+ public static Toast makeText(Context context, CharSequence text, @Duration int duration) {
Toast toast = Toast.makeText(context, text, duration);
toast.getWindowParams().privateFlags |=
WindowManager.LayoutParams.PRIVATE_FLAG_SHOW_FOR_ALL_USERS;
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
index 8501519..653e500 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
@@ -707,10 +707,6 @@
&& !mLockPatternUtils.isLockScreenDisabled(
KeyguardUpdateMonitor.getCurrentUser()),
mSecondaryDisplayShowing, true /* forceCallbacks */);
- } else {
- // The system's keyguard is disabled or missing.
- setShowingLocked(mLockPatternUtils.isSecure(KeyguardUpdateMonitor.getCurrentUser()),
- mSecondaryDisplayShowing, true);
}
mStatusBarKeyguardViewManager =
diff --git a/packages/SystemUI/src/com/android/systemui/power/PowerUI.java b/packages/SystemUI/src/com/android/systemui/power/PowerUI.java
index b43e99b..e661fa7 100644
--- a/packages/SystemUI/src/com/android/systemui/power/PowerUI.java
+++ b/packages/SystemUI/src/com/android/systemui/power/PowerUI.java
@@ -44,6 +44,7 @@
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.logging.MetricsLogger;
+import com.android.settingslib.utils.ThreadUtils;
import com.android.systemui.Dependency;
import com.android.systemui.R;
import com.android.systemui.SystemUI;
@@ -242,7 +243,9 @@
}
// Show the correct version of low battery warning if needed
- maybeShowBatteryWarning(plugged, oldPlugged, oldBucket, bucket);
+ ThreadUtils.postOnBackgroundThread(() -> {
+ maybeShowBatteryWarning(plugged, oldPlugged, oldBucket, bucket);
+ });
} else if (Intent.ACTION_SCREEN_OFF.equals(action)) {
mScreenOffTime = SystemClock.elapsedRealtime();
diff --git a/packages/SystemUI/src/com/android/systemui/qs/AutoAddTracker.java b/packages/SystemUI/src/com/android/systemui/qs/AutoAddTracker.java
index f960dc5..2a2bc09 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/AutoAddTracker.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/AutoAddTracker.java
@@ -51,10 +51,11 @@
public AutoAddTracker(Context context) {
mContext = context;
mAutoAdded = new ArraySet<>(getAdded());
+ // TODO: remove migration code and shared preferences keys after P release
for (String[] convertPref : CONVERT_PREFS) {
if (Prefs.getBoolean(context, convertPref[0], false)) {
setTileAdded(convertPref[1]);
- Prefs.putBoolean(context, convertPref[0], false);
+ Prefs.remove(context, convertPref[0]);
}
}
mContext.getContentResolver().registerContentObserver(
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSFooterImpl.java b/packages/SystemUI/src/com/android/systemui/qs/QSFooterImpl.java
index 92475da..76baee4 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSFooterImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSFooterImpl.java
@@ -84,6 +84,8 @@
protected View mEdit;
private TouchAnimator mAnimator;
+ private View mActionsContainer;
+
public QSFooterImpl(Context context, AttributeSet attrs) {
super(context, attrs);
}
@@ -107,6 +109,8 @@
mMultiUserSwitch = findViewById(R.id.multi_user_switch);
mMultiUserAvatar = mMultiUserSwitch.findViewById(R.id.multi_user_avatar);
+ mActionsContainer = findViewById(R.id.qs_footer_actions_container);
+
// RenderThread is doing more harm than good when touching the header (to expand quick
// settings), so disable it for this view
((RippleDrawable) mSettingsButton.getBackground()).setForceSoftware(true);
@@ -158,10 +162,8 @@
@Nullable
private TouchAnimator createSettingsAlphaAnimator() {
return new TouchAnimator.Builder()
- .addFloat(mEdit, "alpha", 0, 1)
- .addFloat(mMultiUserSwitch, "alpha", 0, 1)
.addFloat(mCarrierText, "alpha", 0, 1)
- .addFloat(mSettingsButton, "alpha", 0, 1)
+ .addFloat(mActionsContainer, "alpha", 0, 1)
.build();
}
@@ -269,6 +271,11 @@
@Override
public void onClick(View v) {
+ // Don't do anything until view are unhidden
+ if (!mExpanded) {
+ return;
+ }
+
if (v == mSettingsButton) {
if (!Dependency.get(DeviceProvisionedController.class).isCurrentUserSetup()) {
// If user isn't setup just unlock the device and dump them back at SUW.
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSFragment.java b/packages/SystemUI/src/com/android/systemui/qs/QSFragment.java
index 669439d..d8e1051 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSFragment.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSFragment.java
@@ -69,7 +69,7 @@
@Override
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container,
Bundle savedInstanceState) {
- inflater =inflater.cloneInContext(new ContextThemeWrapper(getContext(), R.style.qs_theme));
+ inflater = inflater.cloneInContext(new ContextThemeWrapper(getContext(), R.style.qs_theme));
return inflater.inflate(R.layout.qs_panel, container, false);
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSFactoryImpl.java b/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSFactoryImpl.java
index 77c3bfa..bf9746e 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSFactoryImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSFactoryImpl.java
@@ -23,6 +23,7 @@
import com.android.systemui.plugins.qs.QSTileView;
import com.android.systemui.qs.external.CustomTile;
import com.android.systemui.qs.tiles.AirplaneModeTile;
+import com.android.systemui.qs.tiles.AlarmTile;
import com.android.systemui.qs.tiles.BatterySaverTile;
import com.android.systemui.qs.tiles.BluetoothTile;
import com.android.systemui.qs.tiles.CastTile;
@@ -69,6 +70,7 @@
else if (tileSpec.equals("saver")) return new DataSaverTile(mHost);
else if (tileSpec.equals("night")) return new NightDisplayTile(mHost);
else if (tileSpec.equals("nfc")) return new NfcTile(mHost);
+ else if (tileSpec.equals("alarm")) return new AlarmTile(mHost);
// Intent tiles.
else if (tileSpec.startsWith(IntentTile.PREFIX)) return IntentTile.create(mHost, tileSpec);
else if (tileSpec.startsWith(CustomTile.PREFIX)) return CustomTile.create(mHost, tileSpec);
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/AlarmTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/AlarmTile.java
new file mode 100644
index 0000000..ff3fe73
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/AlarmTile.java
@@ -0,0 +1,102 @@
+/*
+ * Copyright (C) 2018 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.systemui.qs.tiles;
+
+import static android.service.quicksettings.Tile.STATE_ACTIVE;
+import static android.service.quicksettings.Tile.STATE_UNAVAILABLE;
+
+import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.QS_ALARM;
+import static com.android.systemui.keyguard.KeyguardSliceProvider.formatNextAlarm;
+
+import android.app.AlarmManager.AlarmClockInfo;
+import android.app.PendingIntent;
+import android.content.Intent;
+import android.provider.AlarmClock;
+
+import com.android.systemui.Dependency;
+import com.android.systemui.R;
+import com.android.systemui.plugins.ActivityStarter;
+import com.android.systemui.qs.QSTileHost;
+import com.android.systemui.qs.tileimpl.QSTileImpl;
+import com.android.systemui.statusbar.policy.NextAlarmController;
+import com.android.systemui.statusbar.policy.NextAlarmController.NextAlarmChangeCallback;
+
+public class AlarmTile extends QSTileImpl implements NextAlarmChangeCallback {
+ private final NextAlarmController mController;
+ private String mNextAlarm;
+ private PendingIntent mIntent;
+
+ public AlarmTile(QSTileHost host) {
+ super(host);
+ mController = Dependency.get(NextAlarmController.class);
+ }
+
+ @Override
+ public State newTileState() {
+ return new BooleanState();
+ }
+
+ @Override
+ protected void handleClick() {
+ if (mIntent != null) {
+ Dependency.get(ActivityStarter.class).postStartActivityDismissingKeyguard(mIntent);
+ }
+ }
+
+ @Override
+ protected void handleUpdateState(State state, Object arg) {
+ state.state = mNextAlarm != null ? STATE_ACTIVE : STATE_UNAVAILABLE;
+ state.label = getTileLabel();
+ state.secondaryLabel = mNextAlarm;
+ state.icon = ResourceIcon.get(R.drawable.stat_sys_alarm);
+ ((BooleanState) state).value = mNextAlarm != null;
+ }
+
+ @Override
+ public void onNextAlarmChanged(AlarmClockInfo nextAlarm) {
+ if (nextAlarm != null) {
+ mNextAlarm = formatNextAlarm(mContext, nextAlarm);
+ mIntent = nextAlarm.getShowIntent();
+ } else {
+ mNextAlarm = null;
+ mIntent = null;
+ }
+ refreshState();
+ }
+
+ @Override
+ public int getMetricsCategory() {
+ return QS_ALARM;
+ }
+
+ @Override
+ public Intent getLongClickIntent() {
+ return new Intent(AlarmClock.ACTION_SET_ALARM);
+ }
+
+ @Override
+ protected void handleSetListening(boolean listening) {
+ if (listening) {
+ mController.addCallback(this);
+ } else {
+ mController.removeCallback(this);
+ }
+ }
+
+ @Override
+ public CharSequence getTileLabel() {
+ return mContext.getString(R.string.status_bar_alarm);
+ }
+}
\ No newline at end of file
diff --git a/packages/SystemUI/src/com/android/systemui/recents/ScreenPinningRequest.java b/packages/SystemUI/src/com/android/systemui/recents/ScreenPinningRequest.java
index 316ad16..57f7818 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/ScreenPinningRequest.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/ScreenPinningRequest.java
@@ -23,15 +23,12 @@
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
-import android.content.res.Configuration;
import android.graphics.PixelFormat;
-import android.graphics.Rect;
import android.graphics.drawable.ColorDrawable;
import android.os.Binder;
import android.os.RemoteException;
import android.util.DisplayMetrics;
import android.view.Gravity;
-import android.view.Surface;
import android.view.View;
import android.view.ViewGroup;
import android.view.WindowManager;
@@ -43,6 +40,9 @@
import android.widget.TextView;
import com.android.systemui.R;
+import com.android.systemui.SysUiServiceProvider;
+import com.android.systemui.statusbar.phone.NavigationBarView;
+import com.android.systemui.statusbar.phone.StatusBar;
import com.android.systemui.util.leak.RotationUtils;
import java.util.ArrayList;
@@ -233,11 +233,30 @@
.setVisibility(View.INVISIBLE);
}
+ StatusBar statusBar = SysUiServiceProvider.getComponent(mContext, StatusBar.class);
+ NavigationBarView navigationBarView = statusBar.getNavigationBarView();
+ final boolean recentsVisible = navigationBarView != null
+ && navigationBarView.isRecentsButtonVisible();
boolean touchExplorationEnabled = mAccessibilityService.isTouchExplorationEnabled();
+ int descriptionStringResId;
+ if (recentsVisible) {
+ mLayout.findViewById(R.id.screen_pinning_recents_group).setVisibility(VISIBLE);
+ mLayout.findViewById(R.id.screen_pinning_home_bg_light).setVisibility(INVISIBLE);
+ mLayout.findViewById(R.id.screen_pinning_home_bg).setVisibility(INVISIBLE);
+ descriptionStringResId = touchExplorationEnabled
+ ? R.string.screen_pinning_description_accessible
+ : R.string.screen_pinning_description;
+ } else {
+ mLayout.findViewById(R.id.screen_pinning_recents_group).setVisibility(INVISIBLE);
+ mLayout.findViewById(R.id.screen_pinning_home_bg_light).setVisibility(VISIBLE);
+ mLayout.findViewById(R.id.screen_pinning_home_bg).setVisibility(VISIBLE);
+ descriptionStringResId = touchExplorationEnabled
+ ? R.string.screen_pinning_description_recents_invisible_accessible
+ : R.string.screen_pinning_description_recents_invisible;
+ }
+
((TextView) mLayout.findViewById(R.id.screen_pinning_description))
- .setText(touchExplorationEnabled
- ? R.string.screen_pinning_description_accessible
- : R.string.screen_pinning_description);
+ .setText(descriptionStringResId);
final int backBgVisibility = touchExplorationEnabled ? View.INVISIBLE : View.VISIBLE;
mLayout.findViewById(R.id.screen_pinning_back_bg).setVisibility(backBgVisibility);
mLayout.findViewById(R.id.screen_pinning_back_bg_light).setVisibility(backBgVisibility);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java b/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java
index 79e9f7b..f5f62b85 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java
@@ -24,6 +24,7 @@
import android.os.IBinder;
import android.os.Looper;
import android.os.Message;
+import android.os.RemoteException;
import android.support.annotation.VisibleForTesting;
import android.util.Pair;
@@ -90,6 +91,8 @@
private static final int MSG_FINGERPRINT_ERROR = 42 << MSG_SHIFT;
private static final int MSG_FINGERPRINT_HIDE = 43 << MSG_SHIFT;
private static final int MSG_SHOW_CHARGING_ANIMATION = 44 << MSG_SHIFT;
+ private static final int MSG_SHOW_PINNING_TOAST_ENTER_EXIT = 45 << MSG_SHIFT;
+ private static final int MSG_SHOW_PINNING_TOAST_ESCAPE = 46 << MSG_SHIFT;
public static final int FLAG_EXCLUDE_NONE = 0;
public static final int FLAG_EXCLUDE_SEARCH_PANEL = 1 << 0;
@@ -148,6 +151,8 @@
default void clickTile(ComponentName tile) { }
default void handleSystemKey(int arg1) { }
+ default void showPinningEnterExitToast(boolean entering) { }
+ default void showPinningEscapeToast() { }
default void handleShowGlobalActionsMenu() { }
default void handleShowShutdownUi(boolean isReboot, String reason) { }
@@ -453,6 +458,21 @@
}
@Override
+ public void showPinningEnterExitToast(boolean entering) {
+ synchronized (mLock) {
+ mHandler.obtainMessage(MSG_SHOW_PINNING_TOAST_ENTER_EXIT, entering).sendToTarget();
+ }
+ }
+
+ @Override
+ public void showPinningEscapeToast() {
+ synchronized (mLock) {
+ mHandler.obtainMessage(MSG_SHOW_PINNING_TOAST_ESCAPE).sendToTarget();
+ }
+ }
+
+
+ @Override
public void showGlobalActionsMenu() {
synchronized (mLock) {
mHandler.removeMessages(MSG_SHOW_GLOBAL_ACTIONS);
@@ -767,6 +787,16 @@
mCallbacks.get(i).showChargingAnimation(msg.arg1);
}
break;
+ case MSG_SHOW_PINNING_TOAST_ENTER_EXIT:
+ for (int i = 0; i < mCallbacks.size(); i++) {
+ mCallbacks.get(i).showPinningEnterExitToast(msg.arg1 != 0);
+ }
+ break;
+ case MSG_SHOW_PINNING_TOAST_ESCAPE:
+ for (int i = 0; i < mCallbacks.size(); i++) {
+ mCallbacks.get(i).showPinningEscapeToast();
+ }
+ break;
}
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShelf.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShelf.java
index 8325df7..cad956c 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShelf.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShelf.java
@@ -802,10 +802,6 @@
updateRelativeOffset();
}
- public void setDarkOffsetX(int offsetX) {
- mShelfIcons.setDarkOffsetX(offsetX);
- }
-
private class ShelfState extends ExpandableViewState {
private float openedAmount;
private boolean hasItemsInStableShelf;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/RowInflaterTask.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/RowInflaterTask.java
index 3491f81..c214171 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/RowInflaterTask.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/RowInflaterTask.java
@@ -18,6 +18,7 @@
import android.content.Context;
import android.support.v4.view.AsyncLayoutInflater;
+import android.util.Log;
import android.view.View;
import android.view.ViewGroup;
@@ -30,15 +31,23 @@
* An inflater task that asynchronously inflates a ExpandableNotificationRow
*/
public class RowInflaterTask implements InflationTask, AsyncLayoutInflater.OnInflateFinishedListener {
+
+ private static final String TAG = "RowInflaterTask";
+ private static final boolean TRACE_ORIGIN = true;
+
private RowInflationFinishedListener mListener;
private NotificationData.Entry mEntry;
private boolean mCancelled;
+ private Throwable mInflateOrigin;
/**
* Inflates a new notificationView. This should not be called twice on this object
*/
public void inflate(Context context, ViewGroup parent, NotificationData.Entry entry,
RowInflationFinishedListener listener) {
+ if (TRACE_ORIGIN) {
+ mInflateOrigin = new Throwable("inflate requested here");
+ }
mListener = listener;
AsyncLayoutInflater inflater = new AsyncLayoutInflater(context);
mEntry = entry;
@@ -54,8 +63,16 @@
@Override
public void onInflateFinished(View view, int resid, ViewGroup parent) {
if (!mCancelled) {
- mEntry.onInflationTaskFinished();
- mListener.onInflationFinished((ExpandableNotificationRow) view);
+ try {
+ mEntry.onInflationTaskFinished();
+ mListener.onInflationFinished((ExpandableNotificationRow) view);
+ } catch (Throwable t) {
+ if (mInflateOrigin != null) {
+ Log.e(TAG, "Error in inflation finished listener: " + t, mInflateOrigin);
+ t.addSuppressed(mInflateOrigin);
+ }
+ throw t;
+ }
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/AutoTileManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/AutoTileManager.java
index 36f9f6b..b220686 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/AutoTileManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/AutoTileManager.java
@@ -14,16 +14,13 @@
package com.android.systemui.statusbar.phone;
+import android.app.AlarmManager.AlarmClockInfo;
import android.content.Context;
import android.os.Handler;
-import android.os.Looper;
import android.provider.Settings.Secure;
-
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.app.ColorDisplayController;
import com.android.systemui.Dependency;
-import com.android.systemui.Prefs;
-import com.android.systemui.Prefs.Key;
import com.android.systemui.qs.AutoAddTracker;
import com.android.systemui.qs.QSTileHost;
import com.android.systemui.qs.SecureSetting;
@@ -31,27 +28,37 @@
import com.android.systemui.statusbar.policy.DataSaverController.Listener;
import com.android.systemui.statusbar.policy.HotspotController;
import com.android.systemui.statusbar.policy.HotspotController.Callback;
+import com.android.systemui.statusbar.policy.NextAlarmController;
+import com.android.systemui.statusbar.policy.NextAlarmController.NextAlarmChangeCallback;
/**
* Manages which tiles should be automatically added to QS.
*/
public class AutoTileManager {
-
public static final String HOTSPOT = "hotspot";
public static final String SAVER = "saver";
public static final String INVERSION = "inversion";
public static final String WORK = "work";
public static final String NIGHT = "night";
+ public static final String ALARM = "alarm";
+
private final Context mContext;
private final QSTileHost mHost;
private final Handler mHandler;
private final AutoAddTracker mAutoTracker;
public AutoTileManager(Context context, QSTileHost host) {
- mAutoTracker = new AutoAddTracker(context);
+ this(context, new AutoAddTracker(context), host,
+ new Handler(Dependency.get(Dependency.BG_LOOPER)));
+ }
+
+ @VisibleForTesting
+ AutoTileManager(Context context, AutoAddTracker autoAddTracker, QSTileHost host,
+ Handler handler) {
+ mAutoTracker = autoAddTracker;
mContext = context;
mHost = host;
- mHandler = new Handler((Looper) Dependency.get(Dependency.BG_LOOPER));
+ mHandler = handler;
if (!mAutoTracker.isAdded(HOTSPOT)) {
Dependency.get(HotspotController.class).addCallback(mHotspotCallback);
}
@@ -76,20 +83,25 @@
if (!mAutoTracker.isAdded(WORK)) {
Dependency.get(ManagedProfileController.class).addCallback(mProfileCallback);
}
-
if (!mAutoTracker.isAdded(NIGHT)
- && ColorDisplayController.isAvailable(mContext)) {
+ && ColorDisplayController.isAvailable(mContext)) {
Dependency.get(ColorDisplayController.class).setListener(mColorDisplayCallback);
}
+ if (!mAutoTracker.isAdded(ALARM)) {
+ Dependency.get(NextAlarmController.class).addCallback(mNextAlarmChangeCallback);
+ }
}
public void destroy() {
- mColorsSetting.setListening(false);
+ if (mColorsSetting != null) {
+ mColorsSetting.setListening(false);
+ }
mAutoTracker.destroy();
Dependency.get(HotspotController.class).removeCallback(mHotspotCallback);
Dependency.get(DataSaverController.class).removeCallback(mDataSaverListener);
Dependency.get(ManagedProfileController.class).removeCallback(mProfileCallback);
Dependency.get(ColorDisplayController.class).setListener(null);
+ Dependency.get(NextAlarmController.class).removeCallback(mNextAlarmChangeCallback);
}
private final ManagedProfileController.Callback mProfileCallback =
@@ -138,6 +150,19 @@
}
};
+ private final NextAlarmChangeCallback mNextAlarmChangeCallback = new NextAlarmChangeCallback() {
+ @Override
+ public void onNextAlarmChanged(AlarmClockInfo nextAlarm) {
+ if (mAutoTracker.isAdded(ALARM)) return;
+ if (nextAlarm != null) {
+ mHost.addTile(ALARM);
+ mAutoTracker.setTileAdded(ALARM);
+ mHandler.post(() -> Dependency.get(NextAlarmController.class)
+ .removeCallback(mNextAlarmChangeCallback));
+ }
+ }
+ };
+
@VisibleForTesting
final ColorDisplayController.Callback mColorDisplayCallback =
new ColorDisplayController.Callback() {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarFragment.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarFragment.java
index 65c45a3..242be71 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarFragment.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarFragment.java
@@ -22,11 +22,13 @@
import static com.android.systemui.statusbar.phone.BarTransitions.MODE_SEMI_TRANSPARENT;
import static com.android.systemui.statusbar.phone.StatusBar.DEBUG_WINDOW_STATE;
import static com.android.systemui.statusbar.phone.StatusBar.dumpBarTransitions;
+import static com.android.systemui.OverviewProxyService.OverviewProxyListener;
import android.accessibilityservice.AccessibilityServiceInfo;
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.animation.ObjectAnimator;
+import android.annotation.IdRes;
import android.annotation.Nullable;
import android.app.ActivityManager;
import android.app.ActivityManagerNative;
@@ -69,6 +71,7 @@
import android.view.accessibility.AccessibilityEvent;
import android.view.accessibility.AccessibilityManager;
import android.view.accessibility.AccessibilityManager.AccessibilityServicesStateChangeListener;
+import android.widget.Button;
import com.android.internal.logging.MetricsLogger;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
@@ -153,6 +156,18 @@
private Animator mRotateShowAnimator;
private Animator mRotateHideAnimator;
+ private final OverviewProxyListener mOverviewProxyListener = new OverviewProxyListener() {
+ @Override
+ public void onConnectionChanged(boolean isConnected) {
+ mNavigationBarView.onOverviewProxyConnectionChanged(isConnected);
+ updateScreenPinningGestures();
+ }
+
+ @Override
+ public void onRecentsAnimationStarted() {
+ mNavigationBarView.setRecentsAnimationStarted(true);
+ }
+ };
// ----- Fragment Lifecycle Callbacks -----
@@ -239,12 +254,14 @@
filter.addAction(Intent.ACTION_SCREEN_ON);
getContext().registerReceiverAsUser(mBroadcastReceiver, UserHandle.ALL, filter, null, null);
notifyNavigationBarScreenOn();
+ mOverviewProxyService.addCallback(mOverviewProxyListener);
}
@Override
public void onDestroyView() {
super.onDestroyView();
mNavigationBarView.getLightTransitionsController().destroy(getContext());
+ mOverviewProxyService.removeCallback(mOverviewProxyListener);
getContext().unregisterReceiver(mBroadcastReceiver);
}
@@ -514,6 +531,7 @@
if (masked != mDisabledFlags1) {
mDisabledFlags1 = masked;
if (mNavigationBarView != null) mNavigationBarView.setDisabledFlags(state1);
+ updateScreenPinningGestures();
}
}
@@ -528,7 +546,7 @@
private boolean shouldDisableNavbarGestures() {
return !mStatusBar.isDeviceProvisioned()
|| (mDisabledFlags1 & StatusBarManager.DISABLE_SEARCH) != 0
- || mOverviewProxyService.getProxy() != null;
+ || mNavigationBarView.getRecentsButton().getVisibility() != View.VISIBLE;
}
private void repositionNavigationBar() {
@@ -540,6 +558,24 @@
((View) mNavigationBarView.getParent()).getLayoutParams());
}
+ private void updateScreenPinningGestures() {
+ if (mNavigationBarView == null) {
+ return;
+ }
+
+ // Change the cancel pin gesture to home and back if recents button is invisible
+ boolean recentsVisible = mNavigationBarView.isRecentsButtonVisible();
+ ButtonDispatcher homeButton = mNavigationBarView.getHomeButton();
+ ButtonDispatcher backButton = mNavigationBarView.getBackButton();
+ if (recentsVisible) {
+ homeButton.setOnLongClickListener(this::onHomeLongClick);
+ backButton.setOnLongClickListener(this::onLongPressBackRecents);
+ } else {
+ homeButton.setOnLongClickListener(this::onLongPressBackHome);
+ backButton.setOnLongClickListener(this::onLongPressBackHome);
+ }
+ }
+
private void notifyNavigationBarScreenOn() {
mNavigationBarView.notifyScreenOn();
}
@@ -649,20 +685,29 @@
mCommandQueue.toggleRecentApps();
}
+ private boolean onLongPressBackHome(View v) {
+ return onLongPressNavigationButtons(v, R.id.back, R.id.home);
+ }
+
+ private boolean onLongPressBackRecents(View v) {
+ return onLongPressNavigationButtons(v, R.id.back, R.id.recent_apps);
+ }
+
/**
- * This handles long-press of both back and recents. They are
- * handled together to capture them both being long-pressed
+ * This handles long-press of both back and recents/home. Back is the common button with
+ * combination of recents if it is visible or home if recents is invisible.
+ * They are handled together to capture them both being long-pressed
* at the same time to exit screen pinning (lock task).
*
- * When accessibility mode is on, only a long-press from recents
+ * When accessibility mode is on, only a long-press from recents/home
* is required to exit.
*
* In all other circumstances we try to pass through long-press events
* for Back, so that apps can still use it. Which can be from two things.
* 1) Not currently in screen pinning (lock task).
- * 2) Back is long-pressed without recents.
+ * 2) Back is long-pressed without recents/home.
*/
- private boolean onLongPressBackRecents(View v) {
+ private boolean onLongPressNavigationButtons(View v, @IdRes int btnId1, @IdRes int btnId2) {
try {
boolean sendBackLongPress = false;
IActivityManager activityManager = ActivityManagerNative.getDefault();
@@ -670,6 +715,7 @@
boolean inLockTaskMode = activityManager.isInLockTaskMode();
if (inLockTaskMode && !touchExplorationEnabled) {
long time = System.currentTimeMillis();
+
// If we recently long-pressed the other button then they were
// long-pressed 'together'
if ((time - mLastLockToAppLongPress) < LOCK_TO_APP_GESTURE_TOLERENCE) {
@@ -677,26 +723,32 @@
// When exiting refresh disabled flags.
mNavigationBarView.setDisabledFlags(mDisabledFlags1, true);
return true;
- } else if ((v.getId() == R.id.back)
- && !mNavigationBarView.getRecentsButton().getCurrentView().isPressed()) {
- // If we aren't pressing recents right now then they presses
- // won't be together, so send the standard long-press action.
- sendBackLongPress = true;
+ } else if (v.getId() == btnId1) {
+ ButtonDispatcher button = btnId2 == R.id.recent_apps
+ ? mNavigationBarView.getRecentsButton()
+ : mNavigationBarView.getHomeButton();
+ if (!button.getCurrentView().isPressed()) {
+ // If we aren't pressing recents/home right now then they presses
+ // won't be together, so send the standard long-press action.
+ sendBackLongPress = true;
+ }
}
mLastLockToAppLongPress = time;
} else {
// If this is back still need to handle sending the long-press event.
- if (v.getId() == R.id.back) {
+ if (v.getId() == btnId1) {
sendBackLongPress = true;
} else if (touchExplorationEnabled && inLockTaskMode) {
- // When in accessibility mode a long press that is recents (not back)
+ // When in accessibility mode a long press that is recents/home (not back)
// should stop lock task.
activityManager.stopSystemLockTaskMode();
// When exiting refresh disabled flags.
mNavigationBarView.setDisabledFlags(mDisabledFlags1, true);
return true;
- } else if (v.getId() == R.id.recent_apps) {
- return onLongPressRecents();
+ } else if (v.getId() == btnId2) {
+ return btnId2 == R.id.recent_apps
+ ? onLongPressRecents()
+ : onHomeLongClick(mNavigationBarView.getHomeButton().getCurrentView());
}
}
if (sendBackLongPress) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java
index de6ecac..cd220a7 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java
@@ -207,23 +207,6 @@
}
}
- private final OverviewProxyListener mOverviewProxyListener = new OverviewProxyListener() {
- @Override
- public void onConnectionChanged(boolean isConnected) {
- updateSlippery();
- setDisabledFlags(mDisabledFlags, true);
- setUpSwipeUpOnboarding(isConnected);
- }
-
- @Override
- public void onRecentsAnimationStarted() {
- mRecentsAnimationStarted = true;
- if (mSwipeUpOnboarding != null) {
- mSwipeUpOnboarding.onRecentsAnimationStarted();
- }
- }
- };
-
public NavigationBarView(Context context, AttributeSet attrs) {
super(context, attrs);
@@ -280,6 +263,19 @@
notifyVerticalChangedListener(mVertical);
}
+ public void setRecentsAnimationStarted(boolean started) {
+ mRecentsAnimationStarted = started;
+ if (mSwipeUpOnboarding != null) {
+ mSwipeUpOnboarding.onRecentsAnimationStarted();
+ }
+ }
+
+ public void onConnectionChanged(boolean isConnected) {
+ updateSlippery();
+ setDisabledFlags(mDisabledFlags, true);
+ setUpSwipeUpOnboarding(isConnected);
+ }
+
@Override
public boolean onTouchEvent(MotionEvent event) {
if (mGestureHelper.onTouchEvent(event)) {
@@ -353,6 +349,10 @@
return mButtonDispatchers;
}
+ public boolean isRecentsButtonVisible() {
+ return getRecentsButton().getVisibility() == View.VISIBLE;
+ }
+
private void updateCarModeIcons(Context ctx) {
mBackCarModeIcon = getDrawable(ctx,
R.drawable.ic_sysbar_back_carmode, R.drawable.ic_sysbar_back_carmode);
@@ -613,6 +613,9 @@
final ViewGroup navbarView = ((ViewGroup) getParent());
final WindowManager.LayoutParams lp = (WindowManager.LayoutParams) navbarView
.getLayoutParams();
+ if (lp == null) {
+ return;
+ }
if (slippery && (lp.flags & WindowManager.LayoutParams.FLAG_SLIPPERY) == 0) {
lp.flags |= WindowManager.LayoutParams.FLAG_SLIPPERY;
changed = true;
@@ -676,6 +679,12 @@
}
}
+ public void onOverviewProxyConnectionChanged(boolean isConnected) {
+ setSlippery(!isConnected);
+ setDisabledFlags(mDisabledFlags, true);
+ setUpSwipeUpOnboarding(isConnected);
+ }
+
@Override
protected void onDraw(Canvas canvas) {
mGestureHelper.onDraw(canvas);
@@ -873,7 +882,6 @@
onPluginDisconnected(null); // Create default gesture helper
Dependency.get(PluginManager.class).addPluginListener(this,
NavGesture.class, false /* Only one */);
- mOverviewProxyService.addCallback(mOverviewProxyListener);
setUpSwipeUpOnboarding(mOverviewProxyService.getProxy() != null);
}
@@ -884,7 +892,6 @@
if (mGestureHelper != null) {
mGestureHelper.destroy();
}
- mOverviewProxyService.removeCallback(mOverviewProxyListener);
setUpSwipeUpOnboarding(false);
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationIconContainer.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationIconContainer.java
index 91cae0a..5cf4c4c 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationIconContainer.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationIconContainer.java
@@ -120,7 +120,6 @@
private boolean mDisallowNextAnimation;
private boolean mAnimationsEnabled = true;
private ArrayMap<String, ArrayList<StatusBarIcon>> mReplacingIcons;
- private int mDarkOffsetX;
// Keep track of the last visible icon so collapsed container can report on its location
private IconState mLastVisibleIconState;
@@ -378,14 +377,6 @@
iconState.xTranslation = getWidth() - iconState.xTranslation - view.getWidth();
}
}
-
- if (mDark && mDarkOffsetX != 0) {
- for (int i = 0; i < childCount; i++) {
- View view = getChildAt(i);
- IconState iconState = mIconStates.get(view);
- iconState.xTranslation += mDarkOffsetX;
- }
- }
}
private float getLayoutEnd() {
@@ -534,10 +525,6 @@
mAnimationsEnabled = enabled;
}
- public void setDarkOffsetX(int offsetX) {
- mDarkOffsetX = offsetX;
- }
-
public void setReplacingIcons(ArrayMap<String, ArrayList<StatusBarIcon>> replacingIcons) {
mReplacingIcons = replacingIcons;
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
index 2111d2e..52d005c 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
@@ -47,6 +47,7 @@
import android.view.WindowInsets;
import android.view.accessibility.AccessibilityEvent;
import android.widget.FrameLayout;
+
import com.android.internal.logging.MetricsLogger;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
import com.android.keyguard.KeyguardStatusView;
@@ -67,14 +68,11 @@
import com.android.systemui.statusbar.NotificationShelf;
import com.android.systemui.statusbar.StatusBarState;
import com.android.systemui.statusbar.notification.ActivityLaunchAnimator;
-import com.android.systemui.statusbar.notification.NotificationUtils;
-import com.android.systemui.statusbar.phone.HeadsUpManagerPhone;
import com.android.systemui.statusbar.policy.KeyguardUserSwitcher;
import com.android.systemui.statusbar.policy.OnHeadsUpChangedListener;
import com.android.systemui.statusbar.stack.NotificationStackScrollLayout;
import com.android.systemui.statusbar.stack.StackStateAnimator;
-import java.util.Collection;
import java.util.List;
public class NotificationPanelView extends PanelView implements
@@ -482,7 +480,7 @@
mTopPaddingAdjustment = mClockPositionResult.stackScrollerPaddingAdjustment;
}
mNotificationStackScroller.setIntrinsicPadding(stackScrollerPadding);
- mNotificationStackScroller.setDarkShelfOffsetX(mClockPositionResult.clockX);
+ mNotificationStackScroller.setAntiBurnInOffsetX(mClockPositionResult.clockX);
mKeyguardBottomArea.setBurnInXOffset(mClockPositionResult.clockX);
requestScrollerTopPaddingUpdate(animate);
}
diff --git a/services/core/java/com/android/server/am/LockTaskNotify.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScreenPinningNotify.java
similarity index 70%
rename from services/core/java/com/android/server/am/LockTaskNotify.java
rename to packages/SystemUI/src/com/android/systemui/statusbar/phone/ScreenPinningNotify.java
index 1dcb0ad..0d07ad9 100644
--- a/services/core/java/com/android/server/am/LockTaskNotify.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScreenPinningNotify.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2013 The Android Open Source Project
+ * Copyright (C) 2018 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.
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package com.android.server.am;
+package com.android.systemui.statusbar.phone;
import android.content.Context;
import android.os.SystemClock;
@@ -22,36 +22,37 @@
import android.view.WindowManager;
import android.widget.Toast;
-import com.android.internal.R;
+import com.android.systemui.R;
+import com.android.systemui.SysUIToast;
/**
* Helper to manage showing/hiding a image to notify them that they are entering or exiting screen
* pinning mode. All exposed methods should be called from a handler thread.
*/
-public class LockTaskNotify {
- private static final String TAG = "LockTaskNotify";
+public class ScreenPinningNotify {
+ private static final String TAG = "ScreenPinningNotify";
private static final long SHOW_TOAST_MINIMUM_INTERVAL = 1000;
private final Context mContext;
private Toast mLastToast;
private long mLastShowToastTime;
- public LockTaskNotify(Context context) {
+ public ScreenPinningNotify(Context context) {
mContext = context;
}
/** Show "Screen pinned" toast. */
void showPinningStartToast() {
- makeAllUserToastAndShow(R.string.lock_to_app_start);
+ makeAllUserToastAndShow(R.string.screen_pinning_start);
}
/** Show "Screen unpinned" toast. */
void showPinningExitToast() {
- makeAllUserToastAndShow(R.string.lock_to_app_exit);
+ makeAllUserToastAndShow(R.string.screen_pinning_exit);
}
/** Show a toast that describes the gesture the user should use to escape pinned mode. */
- void showEscapeToast() {
+ void showEscapeToast(boolean isRecentsButtonVisible) {
long showToastTime = SystemClock.elapsedRealtime();
if ((showToastTime - mLastShowToastTime) < SHOW_TOAST_MINIMUM_INTERVAL) {
Slog.i(TAG, "Ignore toast since it is requested in very short interval.");
@@ -60,14 +61,14 @@
if (mLastToast != null) {
mLastToast.cancel();
}
- mLastToast = makeAllUserToastAndShow(R.string.lock_to_app_toast);
+ mLastToast = makeAllUserToastAndShow(isRecentsButtonVisible
+ ? R.string.screen_pinning_toast
+ : R.string.screen_pinning_toast_recents_invisible);
mLastShowToastTime = showToastTime;
}
private Toast makeAllUserToastAndShow(int resId) {
- Toast toast = Toast.makeText(mContext, resId, Toast.LENGTH_LONG);
- toast.getWindowParams().privateFlags |=
- WindowManager.LayoutParams.PRIVATE_FLAG_SHOW_FOR_ALL_USERS;
+ Toast toast = SysUIToast.makeText(mContext, resId, Toast.LENGTH_LONG);
toast.show();
return toast;
}
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 116e3f9..3777a6c 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
@@ -406,6 +406,13 @@
protected NotificationEntryManager mEntryManager;
protected NotificationViewHierarchyManager mViewHierarchyManager;
+ /**
+ * Helper that is responsible for showing the right toast when a disallowed activity operation
+ * occurred. In pinned mode, we show instructions on how to break out of this mode, whilst in
+ * fully locked mode we only show that unlocking is blocked.
+ */
+ private ScreenPinningNotify mScreenPinningNotify;
+
// for disabling the status bar
private int mDisabled1 = 0;
private int mDisabled2 = 0;
@@ -831,7 +838,7 @@
} catch (RemoteException ex) {
// no window manager? good luck with that
}
-
+ mScreenPinningNotify = new ScreenPinningNotify(mContext);
mStackScroller.setLongPressListener(mEntryManager.getNotificationLongClicker());
mStackScroller.setStatusBar(this);
mStackScroller.setGroupManager(mGroupManager);
@@ -2142,6 +2149,21 @@
}
+ @Override
+ public void showPinningEnterExitToast(boolean entering) {
+ if (entering) {
+ mScreenPinningNotify.showPinningStartToast();
+ } else {
+ mScreenPinningNotify.showPinningExitToast();
+ }
+ }
+
+ @Override
+ public void showPinningEscapeToast() {
+ mScreenPinningNotify.showEscapeToast(getNavigationBarView() == null
+ || getNavigationBarView().isRecentsButtonVisible());
+ }
+
boolean panelsEnabled() {
return (mDisabled1 & StatusBarManager.DISABLE_EXPAND) == 0
&& (mDisabled2 & StatusBarManager.DISABLE2_NOTIFICATION_SHADE) == 0
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java b/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java
index b28e1a9..1b55a5b 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java
@@ -403,6 +403,7 @@
private final int mSeparatorThickness;
private final Rect mTmpRect = new Rect();
private int mClockBottom;
+ private int mAntiBurnInOffsetX;
public NotificationStackScrollLayout(Context context) {
this(context, null);
@@ -3889,9 +3890,14 @@
applyCurrentBackgroundBounds();
updateWillNotDraw();
updateContentHeight();
+ updateAntiBurnInTranslation();
notifyHeightChangeListener(mShelf);
}
+ private void updateAntiBurnInTranslation() {
+ setTranslationX(mAmbientState.isDark() ? mAntiBurnInOffsetX : 0);
+ }
+
/**
* Updates whether or not this Layout will perform its own custom drawing (i.e. whether or
* not {@link #onDraw(Canvas)} is called). This method should be called whenever the
@@ -4473,8 +4479,9 @@
mHeadsUpGoingAwayAnimationsAllowed = headsUpGoingAwayAnimationsAllowed;
}
- public void setDarkShelfOffsetX(int shelfOffsetX) {
- mShelf.setDarkOffsetX(shelfOffsetX);
+ public void setAntiBurnInOffsetX(int antiBurnInOffsetX) {
+ mAntiBurnInOffsetX = antiBurnInOffsetX;
+ updateAntiBurnInTranslation();
}
public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
diff --git a/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogImpl.java b/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogImpl.java
index 001a582..0c6e0f6 100644
--- a/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogImpl.java
@@ -36,7 +36,6 @@
import android.content.res.ColorStateList;
import android.content.res.Resources;
import android.graphics.Color;
-import android.graphics.Rect;
import android.graphics.drawable.ColorDrawable;
import android.media.AudioManager;
import android.media.AudioSystem;
@@ -58,7 +57,6 @@
import android.view.View.AccessibilityDelegate;
import android.view.View.OnAttachStateChangeListener;
import android.view.View.OnClickListener;
-import android.view.View.OnTouchListener;
import android.view.ViewGroup;
import android.view.Window;
import android.view.WindowManager;
@@ -105,6 +103,7 @@
private CustomDialog mDialog;
private ViewGroup mDialogView;
private ViewGroup mDialogRowsView;
+ private ViewGroup mFooter;
private ImageButton mRingerIcon;
private TextView mRingerStatus;
private final List<VolumeRow> mRows = new ArrayList<>();
@@ -202,8 +201,9 @@
hardwareLayout.setOutsideTouchListener(view -> dismiss(DISMISS_REASON_TOUCH_OUTSIDE));
mDialogRowsView = mDialog.findViewById(R.id.volume_dialog_rows);
- mRingerIcon = mDialog.findViewById(R.id.ringer_icon);
- mRingerStatus = mDialog.findViewById(R.id.ringer_status);
+ mFooter = mDialog.findViewById(R.id.footer);
+ mRingerIcon = mFooter.findViewById(R.id.ringer_icon);
+ mRingerStatus = mFooter.findViewById(R.id.ringer_status);
if (mRows.isEmpty()) {
addRow(AudioManager.STREAM_MUSIC,
@@ -340,36 +340,8 @@
row.outputChooser = row.view.findViewById(R.id.output_chooser);
row.outputChooser.setOnClickListener(mClickOutputChooser);
- row.outputChooser.findViewById(R.id.output_chooser_button)
- .setOnClickListener(mClickOutputChooser);
row.connectedDevice = row.view.findViewById(R.id.volume_row_connected_device);
- // forward events above the slider into the slider
- row.view.findViewById(R.id.volume_row_slider_frame)
- .setOnTouchListener(new OnTouchListener() {
- private final Rect mSliderHitRect = new Rect();
- private boolean mDragging;
-
- @SuppressLint("ClickableViewAccessibility")
- @Override
- public boolean onTouch(View v, MotionEvent event) {
- row.slider.getHitRect(mSliderHitRect);
- if (!mDragging && event.getActionMasked() == MotionEvent.ACTION_DOWN
- && event.getY() < mSliderHitRect.top) {
- mDragging = true;
- }
- if (mDragging) {
- event.offsetLocation(-mSliderHitRect.left, -mSliderHitRect.top);
- row.slider.dispatchTouchEvent(event);
- if (event.getActionMasked() == MotionEvent.ACTION_UP
- || event.getActionMasked() == MotionEvent.ACTION_CANCEL) {
- mDragging = false;
- }
- return true;
- }
- return false;
- }
- });
row.icon = row.view.findViewById(R.id.volume_row_icon);
row.icon.setImageResource(iconRes);
if (row.stream != AudioSystem.STREAM_ACCESSIBILITY) {
@@ -412,6 +384,8 @@
if (ss == null) {
return;
}
+ // normal -> vibrate -> silent -> normal (skip vibrate if device doesn't have
+ // a vibrator.
final boolean hasVibrator = mController.hasVibrator();
if (mState.ringerModeInternal == AudioManager.RINGER_MODE_NORMAL) {
if (hasVibrator) {
@@ -419,7 +393,12 @@
} else {
final boolean wasZero = ss.level == 0;
mController.setStreamVolume(AudioManager.STREAM_RING, wasZero ? 1 : 0);
+ mController.setRingerMode(AudioManager.RINGER_MODE_SILENT, false);
}
+ } else if (mState.ringerModeInternal == AudioManager.RINGER_MODE_VIBRATE) {
+ final boolean wasZero = ss.level == 0;
+ mController.setStreamVolume(AudioManager.STREAM_RING, wasZero ? 1 : 0);
+ mController.setRingerMode(AudioManager.RINGER_MODE_SILENT, false);
} else {
mController.setRingerMode(AudioManager.RINGER_MODE_NORMAL, false);
if (ss.level == 0) {
@@ -908,7 +887,6 @@
private final OnClickListener mClickOutputChooser = new OnClickListener() {
@Override
public void onClick(View v) {
- // TODO: log
dismissH(DISMISS_REASON_OUTPUT_CHOOSER);
showOutputChooserH();
}
diff --git a/packages/SystemUI/src/com/android/systemui/volume/VolumeUiLayout.java b/packages/SystemUI/src/com/android/systemui/volume/VolumeUiLayout.java
index 368194e..f50a287 100644
--- a/packages/SystemUI/src/com/android/systemui/volume/VolumeUiLayout.java
+++ b/packages/SystemUI/src/com/android/systemui/volume/VolumeUiLayout.java
@@ -309,6 +309,12 @@
return super.getOutlineProvider();
}
+ @Override
+ public void setPressed(boolean pressed)
+ {
+ // Ignore presses because it activates the seekbar thumb unnecessarily.
+ }
+
public void setOutsideTouchListener(OnClickListener onClickListener) {
mHasOutsideTouch = true;
requestLayout();
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/AutoAddTrackerTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/AutoAddTrackerTest.java
index 40f8059..dfc1852 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/AutoAddTrackerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/AutoAddTrackerTest.java
@@ -30,6 +30,7 @@
import com.android.systemui.Prefs.Key;
import com.android.systemui.SysuiTestCase;
+import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -40,6 +41,11 @@
private AutoAddTracker mAutoTracker;
+ @Before
+ public void setUp() {
+ Secure.putString(mContext.getContentResolver(), Secure.QS_AUTO_ADDED_TILES, "");
+ }
+
@Test
public void testMigration() {
Prefs.putBoolean(mContext, Key.QS_DATA_SAVER_ADDED, true);
@@ -50,7 +56,10 @@
assertTrue(mAutoTracker.isAdded(WORK));
assertFalse(mAutoTracker.isAdded(INVERSION));
+ // These keys have been removed; retrieving their values should always return the default.
+ assertTrue(Prefs.getBoolean(mContext, Key.QS_DATA_SAVER_ADDED, true ));
assertFalse(Prefs.getBoolean(mContext, Key.QS_DATA_SAVER_ADDED, false));
+ assertTrue(Prefs.getBoolean(mContext, Key.QS_WORK_ADDED, true));
assertFalse(Prefs.getBoolean(mContext, Key.QS_WORK_ADDED, false));
mAutoTracker.destroy();
@@ -96,5 +105,4 @@
mAutoTracker.destroy();
}
-
}
\ No newline at end of file
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/AutoTileManagerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/AutoTileManagerTest.java
index a95e3db..2d2db1b 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/AutoTileManagerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/AutoTileManagerTest.java
@@ -18,45 +18,48 @@
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+import android.app.AlarmManager.AlarmClockInfo;
+import android.os.Handler;
import android.support.test.filters.SmallTest;
import android.testing.AndroidTestingRunner;
import android.testing.TestableLooper;
import android.testing.TestableLooper.RunWithLooper;
-
import com.android.internal.app.ColorDisplayController;
import com.android.systemui.Dependency;
-import com.android.systemui.Prefs;
-import com.android.systemui.Prefs.Key;
import com.android.systemui.SysuiTestCase;
+import com.android.systemui.qs.AutoAddTracker;
import com.android.systemui.qs.QSTileHost;
-
-import org.junit.After;
+import com.android.systemui.statusbar.policy.NextAlarmController;
+import com.android.systemui.statusbar.policy.NextAlarmController.NextAlarmChangeCallback;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
-import org.mockito.Mockito;
+import org.mockito.ArgumentCaptor;
+import org.mockito.Captor;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
@RunWith(AndroidTestingRunner.class)
@RunWithLooper
@SmallTest
public class AutoTileManagerTest extends SysuiTestCase {
- private QSTileHost mQsTileHost;
+ @Mock private QSTileHost mQsTileHost;
+ @Mock private AutoAddTracker mAutoAddTracker;
+ @Captor private ArgumentCaptor<NextAlarmChangeCallback> mAlarmCallback;
+
private AutoTileManager mAutoTileManager;
@Before
public void setUp() throws Exception {
- mDependency.injectTestDependency(Dependency.BG_LOOPER,
- TestableLooper.get(this).getLooper());
- Prefs.putBoolean(mContext, Key.QS_NIGHTDISPLAY_ADDED, false);
- mQsTileHost = Mockito.mock(QSTileHost.class);
- mAutoTileManager = new AutoTileManager(mContext, mQsTileHost);
- }
-
- @After
- public void tearDown() throws Exception {
- mAutoTileManager = null;
+ MockitoAnnotations.initMocks(this);
+ mDependency.injectMockDependency(NextAlarmController.class);
+ mAutoTileManager = new AutoTileManager(mContext, mAutoAddTracker,
+ mQsTileHost, new Handler(TestableLooper.get(this).getLooper()));
+ verify(Dependency.get(NextAlarmController.class))
+ .addCallback(mAlarmCallback.capture());
}
@Test
@@ -106,4 +109,30 @@
ColorDisplayController.AUTO_MODE_DISABLED);
verify(mQsTileHost, never()).addTile("night");
}
+
+ @Test
+ public void alarmTileAdded_whenAlarmSet() {
+ mAlarmCallback.getValue().onNextAlarmChanged(new AlarmClockInfo(0, null));
+
+ verify(mQsTileHost).addTile("alarm");
+ verify(mAutoAddTracker).setTileAdded("alarm");
+ }
+
+ @Test
+ public void alarmTileNotAdded_whenAlarmNotSet() {
+ mAlarmCallback.getValue().onNextAlarmChanged(null);
+
+ verify(mQsTileHost, never()).addTile("alarm");
+ verify(mAutoAddTracker, never()).setTileAdded("alarm");
+ }
+
+ @Test
+ public void alarmTileNotAdded_whenAlreadyAdded() {
+ when(mAutoAddTracker.isAdded("alarm")).thenReturn(true);
+
+ mAlarmCallback.getValue().onNextAlarmChanged(new AlarmClockInfo(0, null));
+
+ verify(mQsTileHost, never()).addTile("alarm");
+ verify(mAutoAddTracker, never()).setTileAdded("alarm");
+ }
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayoutTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayoutTest.java
index 1c010b6..d9673d3 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayoutTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayoutTest.java
@@ -61,4 +61,15 @@
Assert.assertFalse(mStackScroller.isDimmed());
}
+ @Test
+ public void testAntiBurnInOffset() {
+ final int burnInOffset = 30;
+ mStackScroller.setAntiBurnInOffsetX(burnInOffset);
+ mStackScroller.setDark(false /* dark */, false /* animated */, null /* touch */);
+ Assert.assertEquals(0 /* expected */, mStackScroller.getTranslationX(), 0.01 /* delta */);
+ mStackScroller.setDark(true /* dark */, false /* animated */, null /* touch */);
+ Assert.assertEquals(burnInOffset /* expected */, mStackScroller.getTranslationX(),
+ 0.01 /* delta */);
+ }
+
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/volume/VolumeDialogImplTest.java b/packages/SystemUI/tests/src/com/android/systemui/volume/VolumeDialogImplTest.java
index 2d28c9f..4888fb2 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/volume/VolumeDialogImplTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/volume/VolumeDialogImplTest.java
@@ -16,12 +16,21 @@
package com.android.systemui.volume;
+import static android.media.AudioManager.RINGER_MODE_NORMAL;
+import static android.media.AudioManager.RINGER_MODE_SILENT;
+import static android.media.AudioManager.RINGER_MODE_VIBRATE;
+import static android.media.AudioManager.STREAM_RING;
+
import static com.android.systemui.volume.Events.DISMISS_REASON_UNKNOWN;
import static com.android.systemui.volume.Events.SHOW_REASON_UNKNOWN;
import static com.android.systemui.volume.VolumeDialogControllerImpl.STREAMS;
import static junit.framework.Assert.assertTrue;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
import android.app.KeyguardManager;
import android.media.AudioManager;
import android.support.test.filters.SmallTest;
@@ -32,8 +41,10 @@
import android.view.ViewGroup;
import android.widget.ImageView;
+import com.android.systemui.R;
import com.android.systemui.SysuiTestCase;
import com.android.systemui.plugins.VolumeDialogController;
+import com.android.systemui.plugins.VolumeDialogController.State;
import com.android.systemui.statusbar.policy.AccessibilityManagerWrapper;
import org.junit.Before;
@@ -70,13 +81,19 @@
mDialog = new VolumeDialogImpl(getContext());
mDialog.init(0, null);
- VolumeDialogController.State state = new VolumeDialogController.State();
+ State state = createShellState();
+ mDialog.onStateChangedH(state);
+ }
+
+ private State createShellState() {
+ State state = new VolumeDialogController.State();
for (int i = AudioManager.STREAM_VOICE_CALL; i <= AudioManager.STREAM_ACCESSIBILITY; i++) {
VolumeDialogController.StreamState ss = new VolumeDialogController.StreamState();
ss.name = STREAMS.get(i);
+ ss.level = 1;
state.states.append(i, ss);
}
- mDialog.onStateChangedH(state);
+ return state;
}
private void navigateViews(View view, Predicate<View> condition) {
@@ -111,4 +128,94 @@
mDialog.dismiss(DISMISS_REASON_UNKNOWN);
}
+ @Test
+ public void testNoDuplicationOfParentState() {
+ mDialog.show(SHOW_REASON_UNKNOWN);
+ ViewGroup dialog = mDialog.getDialogView();
+
+ navigateViews(dialog, view -> !view.isDuplicateParentStateEnabled());
+
+ mDialog.dismiss(DISMISS_REASON_UNKNOWN);
+ }
+
+ @Test
+ public void testNoClickableViewGroups() {
+ mDialog.show(SHOW_REASON_UNKNOWN);
+ ViewGroup dialog = mDialog.getDialogView();
+
+ navigateViews(dialog, view -> {
+ if (view instanceof ViewGroup) {
+ return !view.isClickable();
+ } else {
+ return true;
+ }
+ });
+
+ mDialog.dismiss(DISMISS_REASON_UNKNOWN);
+ }
+
+ @Test
+ public void testTristateToggle_withVibrator() {
+ when(mController.hasVibrator()).thenReturn(true);
+
+ State state = createShellState();
+ state.ringerModeInternal = RINGER_MODE_NORMAL;
+ mDialog.onStateChangedH(state);
+
+ mDialog.show(SHOW_REASON_UNKNOWN);
+ ViewGroup dialog = mDialog.getDialogView();
+
+ // click once, verify updates to vibrate
+ dialog.findViewById(R.id.ringer_icon).performClick();
+ verify(mController, times(1)).setRingerMode(RINGER_MODE_VIBRATE, false);
+
+ // fake the update back to the dialog with the new ringer mode
+ state = createShellState();
+ state.ringerModeInternal = RINGER_MODE_VIBRATE;
+ mDialog.onStateChangedH(state);
+
+ // click once, verify updates to silent
+ dialog.findViewById(R.id.ringer_icon).performClick();
+ verify(mController, times(1)).setRingerMode(RINGER_MODE_SILENT, false);
+ verify(mController, times(1)).setStreamVolume(STREAM_RING, 0);
+
+ // fake the update back to the dialog with the new ringer mode
+ state = createShellState();
+ state.states.get(STREAM_RING).level = 0;
+ state.ringerModeInternal = RINGER_MODE_SILENT;
+ mDialog.onStateChangedH(state);
+
+ // click once, verify updates to normal
+ dialog.findViewById(R.id.ringer_icon).performClick();
+ verify(mController, times(1)).setRingerMode(RINGER_MODE_NORMAL, false);
+ verify(mController, times(1)).setStreamVolume(STREAM_RING, 0);
+ }
+
+ @Test
+ public void testTristateToggle_withoutVibrator() {
+ when(mController.hasVibrator()).thenReturn(false);
+
+ State state = createShellState();
+ state.ringerModeInternal = RINGER_MODE_NORMAL;
+ mDialog.onStateChangedH(state);
+
+ mDialog.show(SHOW_REASON_UNKNOWN);
+ ViewGroup dialog = mDialog.getDialogView();
+
+ // click once, verify updates to silent
+ dialog.findViewById(R.id.ringer_icon).performClick();
+ verify(mController, times(1)).setRingerMode(RINGER_MODE_SILENT, false);
+ verify(mController, times(1)).setStreamVolume(STREAM_RING, 0);
+
+ // fake the update back to the dialog with the new ringer mode
+ state = createShellState();
+ state.states.get(STREAM_RING).level = 0;
+ state.ringerModeInternal = RINGER_MODE_SILENT;
+ mDialog.onStateChangedH(state);
+
+ // click once, verify updates to normal
+ dialog.findViewById(R.id.ringer_icon).performClick();
+ verify(mController, times(1)).setRingerMode(RINGER_MODE_NORMAL, false);
+ verify(mController, times(1)).setStreamVolume(STREAM_RING, 0);
+ }
}
diff --git a/proto/src/metrics_constants.proto b/proto/src/metrics_constants.proto
index 7539d88..01714cf 100644
--- a/proto/src/metrics_constants.proto
+++ b/proto/src/metrics_constants.proto
@@ -5173,6 +5173,18 @@
// OS: P
AUTOFILL_INVALID_PERMISSION = 1289;
+ // OPEN: QS Alarm tile shown
+ // ACTION: QS Alarm tile tapped
+ // SUBTYPE: 0 is off, 1 is on
+ // CATEGORY: QUICK_SETTINGS
+ // OS: P
+ QS_ALARM = 1290;
+
+ // OPEN: Settings->Connected Devices->USB->(click on details link)
+ // CATEGORY: SETTINGS
+ // OS: P
+ USB_DEVICE_DETAILS = 1291;
+
// ---- End P Constants, all P constants go above this line ----
// Add new aosp constants above this line.
// END OF AOSP CONSTANTS
diff --git a/proto/src/system_messages.proto b/proto/src/system_messages.proto
index db70184..08fdb97 100644
--- a/proto/src/system_messages.proto
+++ b/proto/src/system_messages.proto
@@ -200,6 +200,10 @@
// Package: android
NOTE_CARRIER_NETWORK_AVAILABLE = 46;
+ // Inform that USB is configured for Tethering
+ // Package: android
+ NOTE_USB_TETHER = 47;
+
// ADD_NEW_IDS_ABOVE_THIS_LINE
// Legacy IDs with arbitrary values appear below
// Legacy IDs existed as stable non-conflicting constants prior to the O release
diff --git a/proto/src/wifi.proto b/proto/src/wifi.proto
index f5349df..f6a54af 100644
--- a/proto/src/wifi.proto
+++ b/proto/src/wifi.proto
@@ -373,6 +373,9 @@
// Wps connection metrics
optional WpsMetrics wps_metrics = 91;
+
+ // Wifi power statistics
+ optional WifiPowerStats wifi_power_stats = 92;
}
// Information that gets logged for every WiFi connection.
@@ -1134,3 +1137,22 @@
// Total number of wps cancellation
optional int32 num_wps_cancellation = 8;
}
+
+// Power stats for Wifi
+message WifiPowerStats {
+
+ // Duration of log (ms)
+ optional int64 logging_duration_ms = 1;
+
+ // Energy consumed by wifi (mAh)
+ optional double energy_consumed_mah = 2;
+
+ // Amount of time wifi is in idle (ms)
+ optional int64 idle_time_ms = 3;
+
+ // Amount of time wifi is in rx (ms)
+ optional int64 rx_time_ms = 4;
+
+ // Amount of time wifi is in tx (ms)
+ optional int64 tx_time_ms = 5;
+}
\ No newline at end of file
diff --git a/services/autofill/java/com/android/server/autofill/ui/FillUi.java b/services/autofill/java/com/android/server/autofill/ui/FillUi.java
index 5ee3cbf..5f112c7 100644
--- a/services/autofill/java/com/android/server/autofill/ui/FillUi.java
+++ b/services/autofill/java/com/android/server/autofill/ui/FillUi.java
@@ -27,6 +27,7 @@
import android.graphics.Point;
import android.graphics.Rect;
import android.service.autofill.Dataset;
+import android.service.autofill.Dataset.DatasetFieldFilter;
import android.service.autofill.FillResponse;
import android.text.TextUtils;
import android.util.Slog;
@@ -58,6 +59,7 @@
import java.util.Collections;
import java.util.List;
import java.util.regex.Pattern;
+import java.util.stream.Collectors;
final class FillUi {
private static final String TAG = "FillUi";
@@ -185,7 +187,7 @@
final ArrayList<ViewItem> items = new ArrayList<>(totalItems);
if (header != null) {
if (sVerbose) Slog.v(TAG, "adding header");
- items.add(new ViewItem(null, null, null, header));
+ items.add(new ViewItem(null, null, false, null, header));
}
for (int i = 0; i < datasetCount; i++) {
final Dataset dataset = response.getDatasets().get(i);
@@ -205,21 +207,32 @@
Slog.e(TAG, "Error inflating remote views", e);
continue;
}
- final Pattern filter = dataset.getFilter(index);
+ final DatasetFieldFilter filter = dataset.getFilter(index);
+ Pattern filterPattern = null;
String valueText = null;
+ boolean filterable = true;
if (filter == null) {
final AutofillValue value = dataset.getFieldValues().get(index);
if (value != null && value.isText()) {
valueText = value.getTextValue().toString().toLowerCase();
}
+ } else {
+ filterPattern = filter.pattern;
+ if (filterPattern == null) {
+ if (sVerbose) {
+ Slog.v(TAG, "Explicitly disabling filter at id " + focusedViewId
+ + " for dataset #" + index);
+ }
+ filterable = false;
+ }
}
- items.add(new ViewItem(dataset, filter, valueText, view));
+ items.add(new ViewItem(dataset, filterPattern, filterable, valueText, view));
}
}
if (footer != null) {
if (sVerbose) Slog.v(TAG, "adding footer");
- items.add(new ViewItem(null, null, null, footer));
+ items.add(new ViewItem(null, null, false, null, footer));
}
mAdapter = new ItemsAdapter(items);
@@ -354,7 +367,7 @@
MeasureSpec.AT_MOST);
final int itemCount = mAdapter.getCount();
for (int i = 0; i < itemCount; i++) {
- View view = mAdapter.getItem(i).view;
+ final View view = mAdapter.getItem(i).view;
view.measure(widthMeasureSpec, heightMeasureSpec);
final int clampedMeasuredWidth = Math.min(view.getMeasuredWidth(), maxSize.x);
final int newContentWidth = Math.max(mContentWidth, clampedMeasuredWidth);
@@ -400,13 +413,62 @@
public final @Nullable Dataset dataset;
public final @NonNull View view;
public final @Nullable Pattern filter;
+ public final boolean filterable;
- ViewItem(@Nullable Dataset dataset, @Nullable Pattern filter, @Nullable String value,
- @NonNull View view) {
+ /**
+ * Default constructor.
+ *
+ * @param dataset dataset associated with the item or {@code null} if it's a header or
+ * footer (TODO(b/69796626): make @NonNull if header/footer is refactored out of the list)
+ * @param filter optional filter set by the service to determine how the item should be
+ * filtered
+ * @param filterable optional flag set by the service to indicate this item should not be
+ * filtered (typically used when the dataset has value but it's sensitive, like a password)
+ * @param value dataset value
+ * @param view dataset presentation.
+ */
+ ViewItem(@Nullable Dataset dataset, @Nullable Pattern filter, boolean filterable,
+ @Nullable String value, @NonNull View view) {
this.dataset = dataset;
this.value = value;
this.view = view;
this.filter = filter;
+ this.filterable = filterable;
+ }
+
+ /**
+ * Returns whether this item matches the value input by the user so it can be included
+ * in the filtered datasets.
+ */
+ public boolean matches(CharSequence filterText) {
+ if (TextUtils.isEmpty(filterText)) {
+ // Always show item when the user input is empty
+ return true;
+ }
+ if (!filterable) {
+ // Service explicitly disabled filtering using a null Pattern.
+ return false;
+ }
+ final String constraintLowerCase = filterText.toString().toLowerCase();
+ if (filter != null) {
+ // Uses pattern provided by service
+ return filter.matcher(constraintLowerCase).matches();
+ } else {
+ // Compares it with dataset value with dataset
+ return (value == null)
+ ? (dataset.getAuthentication() == null)
+ : value.toLowerCase().startsWith(constraintLowerCase);
+ }
+ }
+
+ @Override
+ public String toString() {
+ return "ViewItem: [dataset=" + (dataset == null ? "null" : dataset.getId())
+ + ", value=" + (value == null ? "null" : value.length() + "_chars")
+ + ", filterable=" + filterable
+ + ", filter=" + (filter == null ? "null" : filter.pattern().length() + "_chars")
+ + ", view=" + view.getAutofillId()
+ + "]";
}
}
@@ -509,7 +571,7 @@
public void dump(PrintWriter pw, String prefix) {
pw.print(prefix); pw.print("mCallback: "); pw.println(mCallback != null);
pw.print(prefix); pw.print("mListView: "); pw.println(mListView);
- pw.print(prefix); pw.print("mAdapter: "); pw.println(mAdapter != null);
+ pw.print(prefix); pw.print("mAdapter: "); pw.println(mAdapter);
pw.print(prefix); pw.print("mFilterText: ");
Helper.printlnRedactedText(pw, mFilterText);
pw.print(prefix); pw.print("mContentWidth: "); pw.println(mContentWidth);
@@ -556,33 +618,14 @@
public Filter getFilter() {
return new Filter() {
@Override
- protected FilterResults performFiltering(CharSequence constraint) {
+ protected FilterResults performFiltering(CharSequence filterText) {
// No locking needed as mAllItems is final an immutable
+ final List<ViewItem> filtered = mAllItems.stream()
+ .filter((item) -> item.matches(filterText))
+ .collect(Collectors.toList());
final FilterResults results = new FilterResults();
- if (TextUtils.isEmpty(constraint)) {
- results.values = mAllItems;
- results.count = mAllItems.size();
- return results;
- }
- final List<ViewItem> filteredItems = new ArrayList<>();
- final String constraintLowerCase = constraint.toString().toLowerCase();
- final int itemCount = mAllItems.size();
- for (int i = 0; i < itemCount; i++) {
- final ViewItem item = mAllItems.get(i);
- final boolean matches;
- if (item.filter != null) {
- matches = item.filter.matcher(constraintLowerCase).matches();
- } else {
- matches = (item.value == null)
- ? (item.dataset.getAuthentication() == null)
- : item.value.toLowerCase().startsWith(constraintLowerCase);
- }
- if (matches) {
- filteredItems.add(item);
- }
- }
- results.values = filteredItems;
- results.count = filteredItems.size();
+ results.values = filtered;
+ results.count = filtered.size();
return results;
}
@@ -624,6 +667,11 @@
public View getView(int position, View convertView, ViewGroup parent) {
return getItem(position).view;
}
+
+ @Override
+ public String toString() {
+ return "ItemsAdapter: [all=" + mAllItems + ", filtered=" + mFilteredItems + "]";
+ }
}
private final class AnnounceFilterResult implements Runnable {
diff --git a/services/core/java/com/android/server/am/LockTaskController.java b/services/core/java/com/android/server/am/LockTaskController.java
index 21f9135..e5762d2 100644
--- a/services/core/java/com/android/server/am/LockTaskController.java
+++ b/services/core/java/com/android/server/am/LockTaskController.java
@@ -38,6 +38,7 @@
import static com.android.server.am.TaskRecord.LOCK_TASK_AUTH_PINNABLE;
import static com.android.server.am.TaskRecord.LOCK_TASK_AUTH_WHITELISTED;
+import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.app.Activity;
@@ -142,14 +143,6 @@
TelecomManager mTelecomManager;
/**
- * Helper that is responsible for showing the right toast when a disallowed activity operation
- * occurred. In pinned mode, we show instructions on how to break out of this mode, whilst in
- * fully locked mode we only show that unlocking is blocked.
- */
- @VisibleForTesting
- LockTaskNotify mLockTaskNotify;
-
- /**
* The chain of tasks in LockTask mode, in the order of when they first entered LockTask mode.
*
* The first task in the list, which started the current LockTask session, is called the root
@@ -475,7 +468,7 @@
getDevicePolicyManager().notifyLockTaskModeChanged(false, null, userId);
}
if (mLockTaskModeState == LOCK_TASK_MODE_PINNED) {
- getLockTaskNotify().showPinningExitToast();
+ getStatusBarService().showPinningEnterExitToast(false /* entering */);
}
} catch (RemoteException ex) {
throw new RuntimeException(ex);
@@ -490,7 +483,11 @@
*/
void showLockTaskToast() {
if (mLockTaskModeState == LOCK_TASK_MODE_PINNED) {
- mHandler.post(() -> getLockTaskNotify().showEscapeToast());
+ try {
+ getStatusBarService().showPinningEscapeToast();
+ } catch (RemoteException e) {
+ Slog.e(TAG, "Failed to send pinning escape toast", e);
+ }
}
}
@@ -582,7 +579,7 @@
// When lock task starts, we disable the status bars.
try {
if (lockTaskModeState == LOCK_TASK_MODE_PINNED) {
- getLockTaskNotify().showPinningStartToast();
+ getStatusBarService().showPinningEnterExitToast(true /* entering */);
}
mLockTaskModeState = lockTaskModeState;
setStatusBarState(lockTaskModeState, userId);
@@ -835,15 +832,6 @@
return mTelecomManager;
}
- // Should only be called on the handler thread
- @NonNull
- private LockTaskNotify getLockTaskNotify() {
- if (mLockTaskNotify == null) {
- mLockTaskNotify = new LockTaskNotify(mContext);
- }
- return mLockTaskNotify;
- }
-
public void dump(PrintWriter pw, String prefix) {
pw.println(prefix + "LockTaskController");
prefix = prefix + " ";
diff --git a/services/core/java/com/android/server/connectivity/Tethering.java b/services/core/java/com/android/server/connectivity/Tethering.java
index be6c4a1..9a9cdbd 100644
--- a/services/core/java/com/android/server/connectivity/Tethering.java
+++ b/services/core/java/com/android/server/connectivity/Tethering.java
@@ -1095,7 +1095,8 @@
if (VDBG) Log.d(TAG, "setUsbTethering(" + enable + ")");
UsbManager usbManager = (UsbManager) mContext.getSystemService(Context.USB_SERVICE);
synchronized (mPublicSync) {
- usbManager.setCurrentFunction(enable ? UsbManager.USB_FUNCTION_RNDIS : null, false);
+ usbManager.setCurrentFunctions(enable ? UsbManager.FUNCTION_RNDIS
+ : UsbManager.FUNCTION_NONE);
}
return ConnectivityManager.TETHER_ERROR_NO_ERROR;
}
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index 7322315..89fbd17 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -9985,8 +9985,7 @@
// priv-apps.
synchronized (mPackages) {
PackageSetting platformPkgSetting = mSettings.mPackages.get("android");
- if (!pkg.packageName.equals("android")
- && (compareSignatures(platformPkgSetting.signatures.mSigningDetails.signatures,
+ if ((compareSignatures(platformPkgSetting.signatures.mSigningDetails.signatures,
pkg.mSigningDetails.signatures) != PackageManager.SIGNATURE_MATCH)) {
scanFlags |= SCAN_AS_PRIVILEGED;
}
@@ -10453,7 +10452,20 @@
pkg.applicationInfo.flags |= ApplicationInfo.FLAG_UPDATED_SYSTEM_APP;
}
- SELinuxMMAC.assignSeInfoValue(pkg);
+ // SELinux sandboxes become more restrictive as targetSdkVersion increases.
+ // To ensure that apps with sharedUserId are placed in the same selinux domain
+ // without breaking any assumptions about access, put them into the least
+ // restrictive targetSdkVersion=25 domain.
+ // TODO(b/72290969): Base this on the actual targetSdkVersion(s) of the apps within the
+ // sharedUserSetting, instead of defaulting to the least restrictive domain.
+ final int targetSdk = (sharedUserSetting != null) ? 25
+ : pkg.applicationInfo.targetSdkVersion;
+ // TODO(b/71593002): isPrivileged for sharedUser and appInfo should never be out of sync.
+ // They currently can be if the sharedUser apps are signed with the platform key.
+ final boolean isPrivileged = (sharedUserSetting != null) ?
+ sharedUserSetting.isPrivileged() | pkg.isPrivileged() : pkg.isPrivileged();
+
+ SELinuxMMAC.assignSeInfoValue(pkg, isPrivileged, targetSdk);
pkg.mExtras = pkgSetting;
pkg.applicationInfo.processName = fixProcessName(
diff --git a/services/core/java/com/android/server/pm/SELinuxMMAC.java b/services/core/java/com/android/server/pm/SELinuxMMAC.java
index fe5b3d4..a9f1528 100644
--- a/services/core/java/com/android/server/pm/SELinuxMMAC.java
+++ b/services/core/java/com/android/server/pm/SELinuxMMAC.java
@@ -315,7 +315,8 @@
*
* @param pkg object representing the package to be labeled.
*/
- public static void assignSeInfoValue(PackageParser.Package pkg) {
+ public static void assignSeInfoValue(PackageParser.Package pkg, boolean isPrivileged,
+ int targetSdkVersion) {
synchronized (sPolicies) {
if (!sPolicyRead) {
if (DEBUG_POLICY) {
@@ -335,10 +336,11 @@
if (pkg.applicationInfo.targetSandboxVersion == 2)
pkg.applicationInfo.seInfo += SANDBOX_V2_STR;
- if (pkg.applicationInfo.isPrivilegedApp())
+ if (isPrivileged) {
pkg.applicationInfo.seInfo += PRIVILEGED_APP_STR;
+ }
- pkg.applicationInfo.seInfo += TARGETSDKVERSION_STR + pkg.applicationInfo.targetSdkVersion;
+ pkg.applicationInfo.seInfo += TARGETSDKVERSION_STR + targetSdkVersion;
if (DEBUG_POLICY_INSTALL) {
Slog.i(TAG, "package (" + pkg.packageName + ") labeled with " +
diff --git a/services/core/java/com/android/server/stats/StatsCompanionService.java b/services/core/java/com/android/server/stats/StatsCompanionService.java
index 648fa6a..f498cdd 100644
--- a/services/core/java/com/android/server/stats/StatsCompanionService.java
+++ b/services/core/java/com/android/server/stats/StatsCompanionService.java
@@ -161,7 +161,8 @@
@Override
public void sendBroadcast(String pkg, String cls) {
- // TODO: Use a pending intent, and enfoceCallingPermission.
+ // TODO: Use a pending intent.
+ enforceCallingPermission();
mContext.sendBroadcastAsUser(new Intent(ACTION_TRIGGER_COLLECTION).setClassName(pkg, cls),
UserHandle.SYSTEM);
}
@@ -239,7 +240,7 @@
}
}
- public final static class AppUpdateReceiver extends BroadcastReceiver {
+ private final static class AppUpdateReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
/**
@@ -284,7 +285,7 @@
}
}
- public final static class AnomalyAlarmReceiver extends BroadcastReceiver {
+ private final static class AnomalyAlarmReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
Slog.i(TAG, "StatsCompanionService believes an anomaly has occurred.");
@@ -304,7 +305,7 @@
}
}
- public final static class PullingAlarmReceiver extends BroadcastReceiver {
+ private final static class PullingAlarmReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
if (DEBUG)
@@ -325,7 +326,7 @@
}
}
- public final static class ShutdownEventReceiver extends BroadcastReceiver {
+ private final static class ShutdownEventReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
/**
diff --git a/services/core/java/com/android/server/statusbar/StatusBarManagerService.java b/services/core/java/com/android/server/statusbar/StatusBarManagerService.java
index adb368b..7c170ae 100644
--- a/services/core/java/com/android/server/statusbar/StatusBarManagerService.java
+++ b/services/core/java/com/android/server/statusbar/StatusBarManagerService.java
@@ -56,7 +56,6 @@
import java.util.ArrayList;
import java.util.List;
-
/**
* A note on locking: We rely on the fact that calls onto mBar are oneway or
* if they are local, that they just enqueue messages to not deadlock.
@@ -525,6 +524,26 @@
}
@Override
+ public void showPinningEnterExitToast(boolean entering) throws RemoteException {
+ if (mBar != null) {
+ try {
+ mBar.showPinningEnterExitToast(entering);
+ } catch (RemoteException ex) {
+ }
+ }
+ }
+
+ @Override
+ public void showPinningEscapeToast() throws RemoteException {
+ if (mBar != null) {
+ try {
+ mBar.showPinningEscapeToast();
+ } catch (RemoteException ex) {
+ }
+ }
+ }
+
+ @Override
public void showFingerprintDialog(Bundle bundle, IFingerprintDialogReceiver receiver) {
if (mBar != null) {
try {
diff --git a/services/core/java/com/android/server/wm/RootWindowContainer.java b/services/core/java/com/android/server/wm/RootWindowContainer.java
index deed7f1..68c8995 100644
--- a/services/core/java/com/android/server/wm/RootWindowContainer.java
+++ b/services/core/java/com/android/server/wm/RootWindowContainer.java
@@ -903,10 +903,26 @@
boolean handleNotObscuredLocked(WindowState w, boolean obscured, boolean syswin) {
final WindowManager.LayoutParams attrs = w.mAttrs;
final int attrFlags = attrs.flags;
+ final boolean onScreen = w.isOnScreen();
final boolean canBeSeen = w.isDisplayedLw();
final int privateflags = attrs.privateFlags;
boolean displayHasContent = false;
+ if (DEBUG_KEEP_SCREEN_ON) {
+ Slog.d(TAG_KEEP_SCREEN_ON, "handleNotObscuredLocked w: " + w
+ + ", w.mHasSurface: " + w.mHasSurface
+ + ", w.isOnScreen(): " + onScreen
+ + ", w.isDisplayedLw(): " + w.isDisplayedLw()
+ + ", w.mAttrs.userActivityTimeout: " + w.mAttrs.userActivityTimeout);
+ }
+ if (w.mHasSurface && onScreen) {
+ if (!syswin && w.mAttrs.userActivityTimeout >= 0 && mUserActivityTimeout < 0) {
+ mUserActivityTimeout = w.mAttrs.userActivityTimeout;
+ if (DEBUG_KEEP_SCREEN_ON) {
+ Slog.d(TAG, "mUserActivityTimeout set to " + mUserActivityTimeout);
+ }
+ }
+ }
if (w.mHasSurface && canBeSeen) {
if ((attrFlags & FLAG_KEEP_SCREEN_ON) != 0) {
mHoldScreen = w.mSession;
@@ -919,9 +935,6 @@
if (!syswin && w.mAttrs.screenBrightness >= 0 && mScreenBrightness < 0) {
mScreenBrightness = w.mAttrs.screenBrightness;
}
- if (!syswin && w.mAttrs.userActivityTimeout >= 0 && mUserActivityTimeout < 0) {
- mUserActivityTimeout = w.mAttrs.userActivityTimeout;
- }
final int type = attrs.type;
// This function assumes that the contents of the default display are processed first
diff --git a/services/tests/servicestests/src/com/android/server/am/LockTaskControllerTest.java b/services/tests/servicestests/src/com/android/server/am/LockTaskControllerTest.java
index d2ae22b..1cbb399 100644
--- a/services/tests/servicestests/src/com/android/server/am/LockTaskControllerTest.java
+++ b/services/tests/servicestests/src/com/android/server/am/LockTaskControllerTest.java
@@ -90,7 +90,6 @@
@Mock private IStatusBarService mStatusBarService;
@Mock private WindowManagerService mWindowManager;
@Mock private LockPatternUtils mLockPatternUtils;
- @Mock private LockTaskNotify mLockTaskNotify;
@Mock private StatusBarManagerInternal mStatusBarManagerInternal;
@Mock private TelecomManager mTelecomManager;
@Mock private RecentTasks mRecentTasks;
@@ -123,7 +122,6 @@
mLockTaskController.mDevicePolicyManager = mDevicePolicyManager;
mLockTaskController.mTelecomManager = mTelecomManager;
mLockTaskController.mLockPatternUtils = mLockPatternUtils;
- mLockTaskController.mLockTaskNotify = mLockTaskNotify;
LocalServices.removeServiceForTest(StatusBarManagerInternal.class);
LocalServices.addService(StatusBarManagerInternal.class, mStatusBarManagerInternal);
@@ -208,7 +206,7 @@
// THEN lock task mode should be started
verifyLockTaskStarted(STATUS_BAR_MASK_PINNED, DISABLE2_NONE);
// THEN screen pinning toast should be shown
- verify(mLockTaskNotify).showPinningStartToast();
+ verify(mStatusBarService).showPinningEnterExitToast(true /* entering */);
}
@Test
@@ -377,7 +375,7 @@
// THEN the keyguard should be shown
verify(mLockPatternUtils).requireCredentialEntry(UserHandle.USER_ALL);
// THEN screen pinning toast should be shown
- verify(mLockTaskNotify).showPinningExitToast();
+ verify(mStatusBarService).showPinningEnterExitToast(false /* entering */);
}
@Test
diff --git a/services/usb/java/com/android/server/usb/UsbDeviceManager.java b/services/usb/java/com/android/server/usb/UsbDeviceManager.java
index e3e5e3e..d3022b4 100644
--- a/services/usb/java/com/android/server/usb/UsbDeviceManager.java
+++ b/services/usb/java/com/android/server/usb/UsbDeviceManager.java
@@ -41,7 +41,6 @@
import android.hardware.usb.UsbManager;
import android.hardware.usb.UsbPort;
import android.hardware.usb.UsbPortStatus;
-import android.hardware.usb.gadget.V1_0.GadgetFunction;
import android.hardware.usb.gadget.V1_0.IUsbGadget;
import android.hardware.usb.gadget.V1_0.IUsbGadgetCallback;
import android.hardware.usb.gadget.V1_0.Status;
@@ -68,6 +67,8 @@
import android.util.Slog;
import com.android.internal.annotations.GuardedBy;
+import com.android.internal.logging.MetricsLogger;
+import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
import com.android.internal.messages.nano.SystemMessageProto.SystemMessage;
import com.android.internal.notification.SystemNotificationChannels;
import com.android.internal.os.SomeArgs;
@@ -86,21 +87,20 @@
import java.util.NoSuchElementException;
import java.util.Scanner;
import java.util.Set;
-import java.util.StringJoiner;
/**
* UsbDeviceManager manages USB state in device mode.
*/
public class UsbDeviceManager implements ActivityManagerInternal.ScreenObserver {
- private static final String TAG = "UsbDeviceManager";
+ private static final String TAG = UsbDeviceManager.class.getSimpleName();
private static final boolean DEBUG = false;
/**
* The SharedPreference setting per user that stores the screen unlocked functions between
* sessions.
*/
- private static final String UNLOCKED_CONFIG_PREF = "usb-screen-unlocked-config-%d";
+ static final String UNLOCKED_CONFIG_PREF = "usb-screen-unlocked-config-%d";
/**
* ro.bootmode value when phone boots into usual Android.
@@ -156,8 +156,6 @@
private static final String ADB_NOTIFICATION_CHANNEL_ID_TV = "usbdevicemanager.adb.tv";
private UsbHandler mHandler;
- private boolean mBootCompleted;
- private boolean mSystemReady;
private final Object mLock = new Object();
@@ -165,22 +163,13 @@
private final ContentResolver mContentResolver;
@GuardedBy("mLock")
private UsbProfileGroupSettingsManager mCurrentSettings;
- private NotificationManager mNotificationManager;
private final boolean mHasUsbAccessory;
- private boolean mUseUsbNotification;
- private boolean mAdbEnabled;
- private boolean mAudioSourceEnabled;
- private boolean mMidiEnabled;
- private int mMidiCard;
- private int mMidiDevice;
+ @GuardedBy("mLock")
private String[] mAccessoryStrings;
private UsbDebuggingManager mDebuggingManager;
- private final UsbAlsaManager mUsbAlsaManager;
- private final UsbSettingsManager mSettingsManager;
- private Intent mBroadcastedIntent;
- private boolean mPendingBootBroadcast;
+ private final UEventObserver mUEventObserver;
+
private static Set<Integer> sBlackListedInterfaces;
- private SharedPreferences mSettings;
static {
sBlackListedInterfaces = new HashSet<>();
@@ -213,7 +202,7 @@
/*
* Listens for uevent messages from the kernel to monitor the USB state
*/
- private final UEventObserver mUEventObserver = new UEventObserver() {
+ private final class UsbUEventObserver extends UEventObserver {
@Override
public void onUEvent(UEventObserver.UEvent event) {
if (DEBUG) Slog.v(TAG, "USB UEVENT: " + event.toString());
@@ -227,7 +216,7 @@
startAccessoryMode();
}
}
- };
+ }
@Override
public void onKeyguardStateChanged(boolean isShowing) {
@@ -257,8 +246,6 @@
public UsbDeviceManager(Context context, UsbAlsaManager alsaManager,
UsbSettingsManager settingsManager) {
mContext = context;
- mUsbAlsaManager = alsaManager;
- mSettingsManager = settingsManager;
mContentResolver = context.getContentResolver();
PackageManager pm = mContext.getPackageManager();
mHasUsbAccessory = pm.hasSystemFeature(PackageManager.FEATURE_USB_ACCESSORY);
@@ -274,16 +261,24 @@
Slog.i(TAG, "USB GADGET HAL not present in the device", e);
}
+ boolean secureAdbEnabled = SystemProperties.getBoolean("ro.adb.secure", false);
+ boolean dataEncrypted = "1".equals(SystemProperties.get("vold.decrypt"));
+ if (secureAdbEnabled && !dataEncrypted) {
+ mDebuggingManager = new UsbDebuggingManager(context);
+ }
+
if (halNotPresent) {
/**
* Initialze the legacy UsbHandler
*/
- mHandler = new UsbHandlerLegacy(FgThread.get().getLooper(), mContext);
+ mHandler = new UsbHandlerLegacy(FgThread.get().getLooper(), mContext, this,
+ mDebuggingManager, alsaManager, settingsManager);
} else {
/**
* Initialize HAL based UsbHandler
*/
- mHandler = new UsbHandlerHal(FgThread.get().getLooper());
+ mHandler = new UsbHandlerHal(FgThread.get().getLooper(), mContext, this,
+ mDebuggingManager, alsaManager, settingsManager);
}
if (nativeIsStartRequested()) {
@@ -291,12 +286,6 @@
startAccessoryMode();
}
- boolean secureAdbEnabled = SystemProperties.getBoolean("ro.adb.secure", false);
- boolean dataEncrypted = "1".equals(SystemProperties.get("vold.decrypt"));
- if (secureAdbEnabled && !dataEncrypted) {
- mDebuggingManager = new UsbDebuggingManager(context);
- }
-
BroadcastReceiver portReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
@@ -347,41 +336,35 @@
mContext.registerReceiver(languageChangedReceiver,
new IntentFilter(Intent.ACTION_LOCALE_CHANGED));
+
+ // Watch for USB configuration changes
+ mUEventObserver = new UsbUEventObserver();
+ mUEventObserver.startObserving(USB_STATE_MATCH);
+ mUEventObserver.startObserving(ACCESSORY_START_MATCH);
+
+ // register observer to listen for settings changes
+ mContentResolver.registerContentObserver(
+ Settings.Global.getUriFor(Settings.Global.ADB_ENABLED),
+ false, new AdbSettingsObserver());
}
- private UsbProfileGroupSettingsManager getCurrentSettings() {
+ UsbProfileGroupSettingsManager getCurrentSettings() {
synchronized (mLock) {
return mCurrentSettings;
}
}
+ String[] getAccessoryStrings() {
+ synchronized (mLock) {
+ return mAccessoryStrings;
+ }
+ }
+
public void systemReady() {
if (DEBUG) Slog.d(TAG, "systemReady");
LocalServices.getService(ActivityManagerInternal.class).registerScreenObserver(this);
- mNotificationManager = (NotificationManager)
- mContext.getSystemService(Context.NOTIFICATION_SERVICE);
-
- // Ensure that the notification channels are set up
- if (isTv()) {
- // TV-specific notification channel
- mNotificationManager.createNotificationChannel(
- new NotificationChannel(ADB_NOTIFICATION_CHANNEL_ID_TV,
- mContext.getString(
- com.android.internal.R.string
- .adb_debugging_notification_channel_tv),
- NotificationManager.IMPORTANCE_HIGH));
- }
-
- // We do not show the USB notification if the primary volume supports mass storage.
- // The legacy mass storage UI will be used instead.
- boolean massStorageSupported;
- final StorageManager storageManager = StorageManager.from(mContext);
- final StorageVolume primary = storageManager.getPrimaryVolume();
- massStorageSupported = primary != null && primary.allowMassStorage();
- mUseUsbNotification = !massStorageSupported && mContext.getResources().getBoolean(
- com.android.internal.R.bool.config_usbChargingMessage);
mHandler.sendEmptyMessage(MSG_SYSTEM_READY);
}
@@ -410,21 +393,19 @@
boolean enableAccessory = (mAccessoryStrings != null &&
mAccessoryStrings[UsbAccessory.MANUFACTURER_STRING] != null &&
mAccessoryStrings[UsbAccessory.MODEL_STRING] != null);
- String functions = null;
- if (enableAccessory && enableAudio) {
- functions = UsbManager.USB_FUNCTION_ACCESSORY + ","
- + UsbManager.USB_FUNCTION_AUDIO_SOURCE;
- } else if (enableAccessory) {
- functions = UsbManager.USB_FUNCTION_ACCESSORY;
- } else if (enableAudio) {
- functions = UsbManager.USB_FUNCTION_AUDIO_SOURCE;
+ long functions = UsbManager.FUNCTION_NONE;
+ if (enableAccessory) {
+ functions |= UsbManager.FUNCTION_ACCESSORY;
+ }
+ if (enableAudio) {
+ functions |= UsbManager.FUNCTION_AUDIO_SOURCE;
}
- if (functions != null) {
+ if (functions != UsbManager.FUNCTION_NONE) {
mHandler.sendMessageDelayed(mHandler.obtainMessage(MSG_ACCESSORY_MODE_ENTER_TIMEOUT),
ACCESSORY_REQUEST_TIMEOUT);
- setCurrentFunctions(functions, false);
+ setCurrentFunctions(functions);
}
}
@@ -451,19 +432,7 @@
}
}
- private boolean isTv() {
- return mContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_LEANBACK);
- }
-
- private SharedPreferences getPinnedSharedPrefs(Context context) {
- final File prefsFile = new File(new File(
- Environment.getDataUserCePackageDirectory(StorageManager.UUID_PRIVATE_INTERNAL,
- context.getUserId(), context.getPackageName()), "shared_prefs"),
- UsbDeviceManager.class.getSimpleName() + ".xml");
- return context.getSharedPreferences(prefsFile, Context.MODE_PRIVATE);
- }
-
- private abstract class UsbHandler extends Handler {
+ abstract static class UsbHandler extends Handler {
// current USB state
private boolean mConnected;
@@ -471,21 +440,40 @@
private boolean mSourcePower;
private boolean mSinkPower;
private boolean mConfigured;
- protected boolean mUsbDataUnlocked;
private boolean mAudioAccessoryConnected;
private boolean mAudioAccessorySupported;
- protected String mCurrentFunctions;
- protected boolean mCurrentFunctionsApplied;
+
private UsbAccessory mCurrentAccessory;
private int mUsbNotificationId;
private boolean mAdbNotificationShown;
- private int mCurrentUser;
private boolean mUsbCharging;
private boolean mHideUsbNotification;
private boolean mSupportsAllCombinations;
- private String mScreenUnlockedFunctions = UsbManager.USB_FUNCTION_NONE;
private boolean mScreenLocked;
- protected boolean mCurrentUsbFunctionsRequested;
+ private boolean mSystemReady;
+ private Intent mBroadcastedIntent;
+ private boolean mPendingBootBroadcast;
+ private boolean mAudioSourceEnabled;
+ private boolean mMidiEnabled;
+ private int mMidiCard;
+ private int mMidiDevice;
+
+ private final Context mContext;
+ private final UsbDebuggingManager mDebuggingManager;
+ private final UsbAlsaManager mUsbAlsaManager;
+ private final UsbSettingsManager mSettingsManager;
+ private NotificationManager mNotificationManager;
+
+ protected long mScreenUnlockedFunctions;
+ protected boolean mAdbEnabled;
+ protected boolean mBootCompleted;
+ protected boolean mCurrentFunctionsApplied;
+ protected boolean mUseUsbNotification;
+ protected long mCurrentFunctions;
+ protected final UsbDeviceManager mUsbDeviceManager;
+ protected final ContentResolver mContentResolver;
+ protected SharedPreferences mSettings;
+ protected int mCurrentUser;
protected boolean mCurrentUsbFunctionsReceived;
/**
@@ -494,31 +482,36 @@
*/
protected static final String USB_PERSISTENT_CONFIG_PROPERTY = "persist.sys.usb.config";
- public UsbHandler(Looper looper) {
+ UsbHandler(Looper looper, Context context, UsbDeviceManager deviceManager,
+ UsbDebuggingManager debuggingManager, UsbAlsaManager alsaManager,
+ UsbSettingsManager settingsManager) {
super(looper);
+ mContext = context;
+ mDebuggingManager = debuggingManager;
+ mUsbDeviceManager = deviceManager;
+ mUsbAlsaManager = alsaManager;
+ mSettingsManager = settingsManager;
+ mContentResolver = context.getContentResolver();
mCurrentUser = ActivityManager.getCurrentUser();
+ mScreenUnlockedFunctions = UsbManager.FUNCTION_NONE;
mScreenLocked = true;
/*
* Use the normal bootmode persistent prop to maintain state of adb across
* all boot modes.
*/
- mAdbEnabled = UsbManager.containsFunction(
- SystemProperties.get(USB_PERSISTENT_CONFIG_PROPERTY),
- UsbManager.USB_FUNCTION_ADB);
+ mAdbEnabled = (UsbManager.usbFunctionsFromString(getSystemProperty(
+ USB_PERSISTENT_CONFIG_PROPERTY, "")) & UsbManager.FUNCTION_ADB) != 0;
- /*
- * Previous versions can set persist config to mtp/ptp but it does not
- * get reset on OTA. Reset the property here instead.
- */
- String persisted = SystemProperties.get(USB_PERSISTENT_CONFIG_PROPERTY);
- if (UsbManager.containsFunction(persisted, UsbManager.USB_FUNCTION_MTP)
- || UsbManager.containsFunction(persisted, UsbManager.USB_FUNCTION_PTP)) {
- SystemProperties.set(USB_PERSISTENT_CONFIG_PROPERTY,
- UsbManager.removeFunction(UsbManager.removeFunction(persisted,
- UsbManager.USB_FUNCTION_MTP), UsbManager.USB_FUNCTION_PTP));
- }
+ // We do not show the USB notification if the primary volume supports mass storage.
+ // The legacy mass storage UI will be used instead.
+ final StorageManager storageManager = StorageManager.from(mContext);
+ final StorageVolume primary = storageManager.getPrimaryVolume();
+
+ boolean massStorageSupported = primary != null && primary.allowMassStorage();
+ mUseUsbNotification = !massStorageSupported && mContext.getResources().getBoolean(
+ com.android.internal.R.bool.config_usbChargingMessage);
}
public void sendMessage(int what, boolean arg) {
@@ -602,20 +595,14 @@
if (DEBUG) Slog.d(TAG, "setAdbEnabled: " + enable);
if (enable != mAdbEnabled) {
mAdbEnabled = enable;
- String oldFunctions = mCurrentFunctions;
- // Persist the adb setting
- String newFunction = applyAdbFunction(SystemProperties.get(
- USB_PERSISTENT_CONFIG_PROPERTY, UsbManager.USB_FUNCTION_NONE));
- SystemProperties.set(USB_PERSISTENT_CONFIG_PROPERTY, newFunction);
-
- // Remove mtp from the config if file transfer is not enabled
- if (oldFunctions.equals(UsbManager.USB_FUNCTION_MTP) &&
- !mUsbDataUnlocked && enable) {
- oldFunctions = UsbManager.USB_FUNCTION_NONE;
+ if (enable) {
+ setSystemProperty(USB_PERSISTENT_CONFIG_PROPERTY, UsbManager.USB_FUNCTION_ADB);
+ } else {
+ setSystemProperty(USB_PERSISTENT_CONFIG_PROPERTY, "");
}
- setEnabledFunctions(oldFunctions, true, mUsbDataUnlocked);
+ setEnabledFunctions(mCurrentFunctions, true);
updateAdbNotification(false);
}
@@ -624,21 +611,7 @@
}
}
- protected String applyAdbFunction(String functions) {
- // Do not pass null pointer to the UsbManager.
- // There isnt a check there.
- if (functions == null) {
- functions = "";
- }
- if (mAdbEnabled) {
- functions = UsbManager.addFunction(functions, UsbManager.USB_FUNCTION_ADB);
- } else {
- functions = UsbManager.removeFunction(functions, UsbManager.USB_FUNCTION_ADB);
- }
- return functions;
- }
-
- private boolean isUsbTransferAllowed() {
+ protected boolean isUsbTransferAllowed() {
UserManager userManager = (UserManager) mContext.getSystemService(Context.USER_SERVICE);
return !userManager.hasUserRestriction(UserManager.DISALLOW_USB_FILE_TRANSFER);
}
@@ -650,12 +623,13 @@
if (mConfigured && enteringAccessoryMode) {
// successfully entered accessory mode
- if (mAccessoryStrings != null) {
- mCurrentAccessory = new UsbAccessory(mAccessoryStrings);
+ String[] accessoryStrings = mUsbDeviceManager.getAccessoryStrings();
+ if (accessoryStrings != null) {
+ mCurrentAccessory = new UsbAccessory(accessoryStrings);
Slog.d(TAG, "entering USB accessory mode: " + mCurrentAccessory);
// defer accessoryAttached if system is not ready
if (mBootCompleted) {
- getCurrentSettings().accessoryAttached(mCurrentAccessory);
+ mUsbDeviceManager.getCurrentSettings().accessoryAttached(mCurrentAccessory);
} // else handle in boot completed
} else {
Slog.e(TAG, "nativeGetAccessoryStrings failed");
@@ -673,17 +647,24 @@
// make sure accessory mode is off
// and restore default functions
Slog.d(TAG, "exited USB accessory mode");
- setEnabledFunctions(null, false, false);
+ setEnabledFunctions(UsbManager.FUNCTION_NONE, false);
if (mCurrentAccessory != null) {
if (mBootCompleted) {
mSettingsManager.usbAccessoryRemoved(mCurrentAccessory);
}
mCurrentAccessory = null;
- mAccessoryStrings = null;
}
}
+ protected SharedPreferences getPinnedSharedPrefs(Context context) {
+ final File prefsFile = new File(new File(
+ Environment.getDataUserCePackageDirectory(StorageManager.UUID_PRIVATE_INTERNAL,
+ context.getUserId(), context.getPackageName()), "shared_prefs"),
+ UsbDeviceManager.class.getSimpleName() + ".xml");
+ return context.getSharedPreferences(prefsFile, Context.MODE_PRIVATE);
+ }
+
private boolean isUsbStateChanged(Intent intent) {
final Set<String> keySet = intent.getExtras().keySet();
if (mBroadcastedIntent == null) {
@@ -706,7 +687,8 @@
return false;
}
- protected void updateUsbStateBroadcastIfNeeded(boolean configChanged) {
+ protected void updateUsbStateBroadcastIfNeeded(long functions,
+ boolean configChanged) {
// send a sticky broadcast containing current USB state
Intent intent = new Intent(UsbManager.ACTION_USB_STATE);
intent.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING
@@ -716,18 +698,14 @@
intent.putExtra(UsbManager.USB_HOST_CONNECTED, mHostConnected);
intent.putExtra(UsbManager.USB_CONFIGURED, mConfigured);
intent.putExtra(UsbManager.USB_DATA_UNLOCKED,
- isUsbTransferAllowed() && mUsbDataUnlocked);
+ isUsbTransferAllowed() && isUsbDataTransferActive(mCurrentFunctions));
intent.putExtra(UsbManager.USB_CONFIG_CHANGED, configChanged);
- if (mCurrentFunctions != null) {
- String[] functions = mCurrentFunctions.split(",");
- for (int i = 0; i < functions.length; i++) {
- final String function = functions[i];
- if (UsbManager.USB_FUNCTION_NONE.equals(function)) {
- continue;
- }
- intent.putExtra(function, true);
- }
+ long remainingFunctions = functions;
+ while (remainingFunctions != 0) {
+ intent.putExtra(UsbManager.usbFunctionsToString(
+ Long.highestOneBit(remainingFunctions)), true);
+ remainingFunctions -= Long.highestOneBit(remainingFunctions);
}
// send broadcast intent only if the USB state has changed
@@ -739,18 +717,21 @@
}
if (DEBUG) Slog.d(TAG, "broadcasting " + intent + " extras: " + intent.getExtras());
- mContext.sendStickyBroadcastAsUser(intent, UserHandle.ALL);
+ sendStickyBroadcast(intent);
mBroadcastedIntent = intent;
}
+ protected void sendStickyBroadcast(Intent intent) {
+ mContext.sendStickyBroadcastAsUser(intent, UserHandle.ALL);
+ }
+
private void updateUsbFunctions() {
updateAudioSourceFunction();
updateMidiFunction();
}
private void updateAudioSourceFunction() {
- boolean enabled = UsbManager.containsFunction(mCurrentFunctions,
- UsbManager.USB_FUNCTION_AUDIO_SOURCE);
+ boolean enabled = (mCurrentFunctions & UsbManager.FUNCTION_AUDIO_SOURCE) != 0;
if (enabled != mAudioSourceEnabled) {
int card = -1;
int device = -1;
@@ -775,8 +756,7 @@
}
private void updateMidiFunction() {
- boolean enabled = UsbManager.containsFunction(mCurrentFunctions,
- UsbManager.USB_FUNCTION_MIDI);
+ boolean enabled = (mCurrentFunctions & UsbManager.FUNCTION_MIDI) != 0;
if (enabled != mMidiEnabled) {
if (enabled) {
Scanner scanner = null;
@@ -800,11 +780,21 @@
}
private void setScreenUnlockedFunctions() {
- setEnabledFunctions(mScreenUnlockedFunctions, false,
- UsbManager.containsFunction(mScreenUnlockedFunctions,
- UsbManager.USB_FUNCTION_MTP)
- || UsbManager.containsFunction(mScreenUnlockedFunctions,
- UsbManager.USB_FUNCTION_PTP));
+ setEnabledFunctions(mScreenUnlockedFunctions, false);
+ }
+
+ /**
+ * Returns the functions that are passed down to the low level driver once adb and
+ * charging are accounted for.
+ */
+ long getAppliedFunctions(long functions) {
+ if (functions == UsbManager.FUNCTION_NONE) {
+ return getChargingFunctions();
+ }
+ if (mAdbEnabled) {
+ return functions | UsbManager.FUNCTION_ADB;
+ }
+ return functions;
}
@Override
@@ -817,10 +807,10 @@
updateUsbNotification(false);
updateAdbNotification(false);
if (mBootCompleted) {
- updateUsbStateBroadcastIfNeeded(false);
+ updateUsbStateBroadcastIfNeeded(getAppliedFunctions(mCurrentFunctions),
+ false);
}
- if (UsbManager.containsFunction(mCurrentFunctions,
- UsbManager.USB_FUNCTION_ACCESSORY)) {
+ if ((mCurrentFunctions & UsbManager.FUNCTION_ACCESSORY) != 0) {
updateCurrentAccessory();
}
if (mBootCompleted) {
@@ -828,11 +818,10 @@
&& !hasMessages(MSG_FUNCTION_SWITCH_TIMEOUT)) {
// restore defaults when USB is disconnected
if (!mScreenLocked
- && !UsbManager.USB_FUNCTION_NONE.equals(
- mScreenUnlockedFunctions)) {
+ && mScreenUnlockedFunctions != UsbManager.FUNCTION_NONE) {
setScreenUnlockedFunctions();
} else {
- setEnabledFunctions(null, !mAdbEnabled, false);
+ setEnabledFunctions(UsbManager.FUNCTION_NONE, !mAdbEnabled);
}
}
updateUsbFunctions();
@@ -867,7 +856,8 @@
updateUsbNotification(false);
if (mBootCompleted) {
if (mHostConnected || prevHostConnected) {
- updateUsbStateBroadcastIfNeeded(false);
+ updateUsbStateBroadcastIfNeeded(getAppliedFunctions(mCurrentFunctions),
+ false);
}
} else {
mPendingBootBroadcast = true;
@@ -913,17 +903,17 @@
setAdbEnabled(msg.arg1 == 1);
break;
case MSG_SET_CURRENT_FUNCTIONS:
- String functions = (String) msg.obj;
- setEnabledFunctions(functions, false, msg.arg1 == 1);
+ long functions = (Long) msg.obj;
+ setEnabledFunctions(functions, false);
break;
case MSG_SET_SCREEN_UNLOCKED_FUNCTIONS:
- mScreenUnlockedFunctions = (String) msg.obj;
+ mScreenUnlockedFunctions = (Long) msg.obj;
SharedPreferences.Editor editor = mSettings.edit();
editor.putString(String.format(Locale.ENGLISH, UNLOCKED_CONFIG_PREF,
- mCurrentUser), mScreenUnlockedFunctions);
+ mCurrentUser),
+ UsbManager.usbFunctionsToString(mScreenUnlockedFunctions));
editor.commit();
- if (!mScreenLocked && !UsbManager.USB_FUNCTION_NONE.equals(
- mScreenUnlockedFunctions)) {
+ if (!mScreenLocked && mScreenUnlockedFunctions != UsbManager.FUNCTION_NONE) {
// If the screen is unlocked, also set current functions.
setScreenUnlockedFunctions();
}
@@ -936,22 +926,21 @@
if (mSettings == null && !mScreenLocked) {
// Shared preferences aren't accessible until the user has been unlocked.
mSettings = getPinnedSharedPrefs(mContext);
- mScreenUnlockedFunctions = mSettings.getString(
+ mScreenUnlockedFunctions = UsbManager.usbFunctionsFromString(
+ mSettings.getString(
String.format(Locale.ENGLISH, UNLOCKED_CONFIG_PREF, mCurrentUser),
- UsbManager.USB_FUNCTION_NONE);
+ ""));
}
if (!mBootCompleted) {
break;
}
if (mScreenLocked) {
if (!mConnected) {
- setEnabledFunctions(null, false, false);
+ setEnabledFunctions(UsbManager.FUNCTION_NONE, false);
}
} else {
- if (!UsbManager.USB_FUNCTION_NONE.equals(mScreenUnlockedFunctions)
- && (UsbManager.USB_FUNCTION_ADB.equals(mCurrentFunctions)
- || (UsbManager.USB_FUNCTION_MTP.equals(mCurrentFunctions)
- && !mUsbDataUnlocked))) {
+ if (mScreenUnlockedFunctions != UsbManager.FUNCTION_NONE
+ && mCurrentFunctions == UsbManager.FUNCTION_NONE) {
// Set the screen unlocked functions if current function is charging.
setScreenUnlockedFunctions();
}
@@ -959,13 +948,24 @@
break;
case MSG_UPDATE_USER_RESTRICTIONS:
// Restart the USB stack if USB transfer is enabled but no longer allowed.
- final boolean forceRestart = mUsbDataUnlocked
- && isUsbDataTransferActive()
- && !isUsbTransferAllowed();
- setEnabledFunctions(
- mCurrentFunctions, forceRestart, mUsbDataUnlocked && !forceRestart);
+ if (isUsbDataTransferActive(mCurrentFunctions) && !isUsbTransferAllowed()) {
+ setEnabledFunctions(UsbManager.FUNCTION_NONE, true);
+ }
break;
case MSG_SYSTEM_READY:
+ mNotificationManager = (NotificationManager)
+ mContext.getSystemService(Context.NOTIFICATION_SERVICE);
+
+ // Ensure that the notification channels are set up
+ if (isTv()) {
+ // TV-specific notification channel
+ mNotificationManager.createNotificationChannel(
+ new NotificationChannel(ADB_NOTIFICATION_CHANNEL_ID_TV,
+ mContext.getString(
+ com.android.internal.R.string
+ .adb_debugging_notification_channel_tv),
+ NotificationManager.IMPORTANCE_HIGH));
+ }
mSystemReady = true;
finishBoot();
break;
@@ -984,10 +984,14 @@
}
mCurrentUser = msg.arg1;
mScreenLocked = true;
- mScreenUnlockedFunctions = mSettings.getString(
- String.format(Locale.ENGLISH, UNLOCKED_CONFIG_PREF, mCurrentUser),
- UsbManager.USB_FUNCTION_NONE);
- setEnabledFunctions(null, false, false);
+ if (mSettings != null) {
+ mScreenUnlockedFunctions = UsbManager.usbFunctionsFromString(
+ mSettings.getString(
+ String.format(Locale.ENGLISH, UNLOCKED_CONFIG_PREF,
+ mCurrentUser),
+ ""));
+ }
+ setEnabledFunctions(UsbManager.FUNCTION_NONE, false);
}
break;
}
@@ -995,9 +999,7 @@
if (DEBUG) {
Slog.v(TAG, "Accessory mode enter timeout: " + mConnected);
}
- if (!mConnected || !UsbManager.containsFunction(
- mCurrentFunctions,
- UsbManager.USB_FUNCTION_ACCESSORY)) {
+ if (!mConnected || (mCurrentFunctions & UsbManager.FUNCTION_ACCESSORY) == 0) {
notifyAccessoryModeExit();
}
break;
@@ -1008,17 +1010,17 @@
protected void finishBoot() {
if (mBootCompleted && mCurrentUsbFunctionsReceived && mSystemReady) {
if (mPendingBootBroadcast) {
- updateUsbStateBroadcastIfNeeded(false);
+ updateUsbStateBroadcastIfNeeded(getAppliedFunctions(mCurrentFunctions), false);
mPendingBootBroadcast = false;
}
if (!mScreenLocked
- && !UsbManager.USB_FUNCTION_NONE.equals(mScreenUnlockedFunctions)) {
+ && mScreenUnlockedFunctions != UsbManager.FUNCTION_NONE) {
setScreenUnlockedFunctions();
} else {
- setEnabledFunctions(null, false, false);
+ setEnabledFunctions(UsbManager.FUNCTION_NONE, false);
}
if (mCurrentAccessory != null) {
- getCurrentSettings().accessoryAttached(mCurrentAccessory);
+ mUsbDeviceManager.getCurrentSettings().accessoryAttached(mCurrentAccessory);
}
if (mDebuggingManager != null) {
mDebuggingManager.setAdbEnabled(mAdbEnabled);
@@ -1026,8 +1028,8 @@
// make sure the ADB_ENABLED setting value matches the current state
try {
- Settings.Global.putInt(mContentResolver,
- Settings.Global.ADB_ENABLED, mAdbEnabled ? 1 : 0);
+ putGlobalSettings(mContentResolver, Settings.Global.ADB_ENABLED,
+ mAdbEnabled ? 1 : 0);
} catch (SecurityException e) {
// If UserManager.DISALLOW_DEBUGGING_FEATURES is on, that this setting can't
// be changed.
@@ -1040,9 +1042,9 @@
}
}
- private boolean isUsbDataTransferActive() {
- return UsbManager.containsFunction(mCurrentFunctions, UsbManager.USB_FUNCTION_MTP)
- || UsbManager.containsFunction(mCurrentFunctions, UsbManager.USB_FUNCTION_PTP);
+ protected boolean isUsbDataTransferActive(long functions) {
+ return (functions & UsbManager.FUNCTION_MTP) != 0
+ || (functions & UsbManager.FUNCTION_PTP) != 0;
}
public UsbAccessory getCurrentAccessory() {
@@ -1051,7 +1053,7 @@
protected void updateUsbNotification(boolean force) {
if (mNotificationManager == null || !mUseUsbNotification
- || ("0".equals(SystemProperties.get("persist.charging.notify")))) {
+ || ("0".equals(getSystemProperty("persist.charging.notify", "")))) {
return;
}
@@ -1070,30 +1072,37 @@
int id = 0;
int titleRes = 0;
Resources r = mContext.getResources();
+ CharSequence message = r.getText(
+ com.android.internal.R.string.usb_notification_message);
if (mAudioAccessoryConnected && !mAudioAccessorySupported) {
titleRes = com.android.internal.R.string.usb_unsupported_audio_accessory_title;
id = SystemMessage.NOTE_USB_AUDIO_ACCESSORY_NOT_SUPPORTED;
} else if (mConnected) {
- if (UsbManager.containsFunction(mCurrentFunctions,
- UsbManager.USB_FUNCTION_MTP) && mUsbDataUnlocked) {
+ if (mCurrentFunctions == UsbManager.FUNCTION_MTP) {
titleRes = com.android.internal.R.string.usb_mtp_notification_title;
id = SystemMessage.NOTE_USB_MTP;
- } else if (UsbManager.containsFunction(mCurrentFunctions,
- UsbManager.USB_FUNCTION_PTP) && mUsbDataUnlocked) {
+ } else if (mCurrentFunctions == UsbManager.FUNCTION_PTP) {
titleRes = com.android.internal.R.string.usb_ptp_notification_title;
id = SystemMessage.NOTE_USB_PTP;
- } else if (UsbManager.containsFunction(mCurrentFunctions,
- UsbManager.USB_FUNCTION_MIDI)) {
+ } else if (mCurrentFunctions == UsbManager.FUNCTION_MIDI) {
titleRes = com.android.internal.R.string.usb_midi_notification_title;
id = SystemMessage.NOTE_USB_MIDI;
- } else if (UsbManager.containsFunction(mCurrentFunctions,
- UsbManager.USB_FUNCTION_ACCESSORY)) {
+ } else if (mCurrentFunctions == UsbManager.FUNCTION_RNDIS) {
+ titleRes = com.android.internal.R.string.usb_tether_notification_title;
+ id = SystemMessage.NOTE_USB_TETHER;
+ } else if (mCurrentFunctions == UsbManager.FUNCTION_ACCESSORY) {
titleRes = com.android.internal.R.string.usb_accessory_notification_title;
id = SystemMessage.NOTE_USB_ACCESSORY;
- } else if (mSourcePower) {
- titleRes = com.android.internal.R.string.usb_supplying_notification_title;
- id = SystemMessage.NOTE_USB_SUPPLYING;
- } else {
+ }
+ if (mSourcePower) {
+ if (titleRes != 0) {
+ message = r.getText(
+ com.android.internal.R.string.usb_power_notification_message);
+ } else {
+ titleRes = com.android.internal.R.string.usb_supplying_notification_title;
+ id = SystemMessage.NOTE_USB_SUPPLYING;
+ }
+ } else if (titleRes == 0) {
titleRes = com.android.internal.R.string.usb_charging_notification_title;
id = SystemMessage.NOTE_USB_CHARGING;
}
@@ -1113,7 +1122,6 @@
mUsbNotificationId = 0;
}
if (id != 0) {
- CharSequence message;
CharSequence title = r.getText(titleRes);
PendingIntent pi;
String channel;
@@ -1123,12 +1131,10 @@
.usb_unsupported_audio_accessory_title) {
Intent intent = Intent.makeRestartActivityTask(
new ComponentName("com.android.settings",
- "com.android.settings.deviceinfo.UsbModeChooserActivity"));
+ "com.android.settings.Settings$UsbDetailsActivity"));
pi = PendingIntent.getActivityAsUser(mContext, 0,
intent, 0, null, UserHandle.CURRENT);
channel = SystemNotificationChannels.USB;
- message = r.getText(
- com.android.internal.R.string.usb_notification_message);
} else {
final Intent intent = new Intent();
intent.setClassName("com.android.settings",
@@ -1184,7 +1190,7 @@
final int titleRes = com.android.internal.R.string.adb_active_notification_title;
if (mAdbEnabled && mConnected) {
- if ("0".equals(SystemProperties.get("persist.adb.notify"))) return;
+ if ("0".equals(getSystemProperty("persist.adb.notify", ""))) return;
if (force && mAdbNotificationShown) {
mAdbNotificationShown = false;
@@ -1230,20 +1236,41 @@
}
}
- protected String getChargingFunctions() {
+ private boolean isTv() {
+ return mContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_LEANBACK);
+ }
+
+ protected long getChargingFunctions() {
// if ADB is enabled, reset functions to ADB
// else enable MTP as usual.
if (mAdbEnabled) {
- return UsbManager.USB_FUNCTION_ADB;
+ return UsbManager.FUNCTION_ADB;
} else {
- return UsbManager.USB_FUNCTION_MTP;
+ return UsbManager.FUNCTION_MTP;
}
}
- public boolean isFunctionEnabled(String function) {
- return UsbManager.containsFunction(mCurrentFunctions, function);
+ protected void setSystemProperty(String prop, String val) {
+ SystemProperties.set(prop, val);
}
+ protected String getSystemProperty(String prop, String def) {
+ return SystemProperties.get(prop, def);
+ }
+
+ protected void putGlobalSettings(ContentResolver contentResolver, String setting, int val) {
+ Settings.Global.putInt(contentResolver, setting, val);
+ }
+
+ public long getEnabledFunctions() {
+ return mCurrentFunctions;
+ }
+
+ public long getScreenUnlockedFunctions() {
+ return mScreenUnlockedFunctions;
+ }
+
+
public void dump(IndentingPrintWriter pw) {
pw.println("USB Device State:");
pw.println(" mCurrentFunctions: " + mCurrentFunctions);
@@ -1252,7 +1279,6 @@
pw.println(" mScreenLocked: " + mScreenLocked);
pw.println(" mConnected: " + mConnected);
pw.println(" mConfigured: " + mConfigured);
- pw.println(" mUsbDataUnlocked: " + mUsbDataUnlocked);
pw.println(" mCurrentAccessory: " + mCurrentAccessory);
pw.println(" mHostConnected: " + mHostConnected);
pw.println(" mSourcePower: " + mSourcePower);
@@ -1275,12 +1301,10 @@
/**
* Evaluates USB function policies and applies the change accordingly.
*/
- protected abstract void setEnabledFunctions(String functions, boolean forceRestart,
- boolean usbDataUnlocked);
-
+ protected abstract void setEnabledFunctions(long functions, boolean forceRestart);
}
- private final class UsbHandlerLegacy extends UsbHandler {
+ private static final class UsbHandlerLegacy extends UsbHandler {
/**
* The non-persistent property which stores the current USB settings.
*/
@@ -1293,46 +1317,44 @@
private HashMap<String, HashMap<String, Pair<String, String>>> mOemModeMap;
private String mCurrentOemFunctions;
+ private String mCurrentFunctionsStr;
+ private boolean mUsbDataUnlocked;
- UsbHandlerLegacy(Looper looper, Context context) {
- super(looper);
+ UsbHandlerLegacy(Looper looper, Context context, UsbDeviceManager deviceManager,
+ UsbDebuggingManager debuggingManager, UsbAlsaManager alsaManager,
+ UsbSettingsManager settingsManager) {
+ super(looper, context, deviceManager, debuggingManager, alsaManager, settingsManager);
try {
readOemUsbOverrideConfig(context);
// Restore default functions.
- mCurrentOemFunctions = SystemProperties.get(getPersistProp(false),
+ mCurrentOemFunctions = getSystemProperty(getPersistProp(false),
UsbManager.USB_FUNCTION_NONE);
if (isNormalBoot()) {
- mCurrentFunctions = SystemProperties.get(USB_CONFIG_PROPERTY,
+ mCurrentFunctionsStr = getSystemProperty(USB_CONFIG_PROPERTY,
UsbManager.USB_FUNCTION_NONE);
- mCurrentFunctionsApplied = mCurrentFunctions.equals(
- SystemProperties.get(USB_STATE_PROPERTY));
+ mCurrentFunctionsApplied = mCurrentFunctionsStr.equals(
+ getSystemProperty(USB_STATE_PROPERTY, UsbManager.USB_FUNCTION_NONE));
} else {
- mCurrentFunctions = SystemProperties.get(getPersistProp(true),
+ mCurrentFunctionsStr = getSystemProperty(getPersistProp(true),
UsbManager.USB_FUNCTION_NONE);
- mCurrentFunctionsApplied = SystemProperties.get(USB_CONFIG_PROPERTY,
+ mCurrentFunctionsApplied = getSystemProperty(USB_CONFIG_PROPERTY,
UsbManager.USB_FUNCTION_NONE).equals(
- SystemProperties.get(USB_STATE_PROPERTY));
+ getSystemProperty(USB_STATE_PROPERTY, UsbManager.USB_FUNCTION_NONE));
}
+ // Mask out adb, since it is stored in mAdbEnabled
+ mCurrentFunctions = UsbManager.usbFunctionsFromString(mCurrentFunctionsStr)
+ & ~UsbManager.FUNCTION_ADB;
mCurrentUsbFunctionsReceived = true;
String state = FileUtils.readTextFile(new File(STATE_PATH), 0, null).trim();
updateState(state);
-
- // register observer to listen for settings changes
- mContentResolver.registerContentObserver(
- Settings.Global.getUriFor(Settings.Global.ADB_ENABLED),
- false, new AdbSettingsObserver());
-
- // Watch for USB configuration changes
- mUEventObserver.startObserving(USB_STATE_MATCH);
- mUEventObserver.startObserving(ACCESSORY_START_MATCH);
} catch (Exception e) {
Slog.e(TAG, "Error initializing UsbHandler", e);
}
}
private void readOemUsbOverrideConfig(Context context) {
- String[] configList = mContext.getResources().getStringArray(
+ String[] configList = context.getResources().getStringArray(
com.android.internal.R.array.config_oemUsbModeOverride);
if (configList != null) {
@@ -1367,7 +1389,7 @@
return usbFunctions;
}
- String bootMode = SystemProperties.get(BOOT_MODE_PROPERTY, "unknown");
+ String bootMode = getSystemProperty(BOOT_MODE_PROPERTY, "unknown");
Slog.d(TAG, "applyOemOverride usbfunctions=" + usbFunctions + " bootmode=" + bootMode);
Map<String, Pair<String, String>> overridesMap =
@@ -1386,25 +1408,22 @@
if (!overrideFunctions.second.equals("")) {
String newFunction;
if (mAdbEnabled) {
- newFunction = UsbManager.addFunction(overrideFunctions.second,
+ newFunction = addFunction(overrideFunctions.second,
UsbManager.USB_FUNCTION_ADB);
} else {
newFunction = overrideFunctions.second;
}
Slog.d(TAG, "OEM USB override persisting: " + newFunction + "in prop: "
+ getPersistProp(false));
- SystemProperties.set(getPersistProp(false),
- newFunction);
+ setSystemProperty(getPersistProp(false), newFunction);
}
return overrideFunctions.first;
} else if (mAdbEnabled) {
- String newFunction = UsbManager.addFunction(UsbManager.USB_FUNCTION_NONE,
+ String newFunction = addFunction(UsbManager.USB_FUNCTION_NONE,
UsbManager.USB_FUNCTION_ADB);
- SystemProperties.set(getPersistProp(false),
- newFunction);
+ setSystemProperty(getPersistProp(false), newFunction);
} else {
- SystemProperties.set(getPersistProp(false),
- UsbManager.USB_FUNCTION_NONE);
+ setSystemProperty(getPersistProp(false), UsbManager.USB_FUNCTION_NONE);
}
}
// return passed in functions as is.
@@ -1417,7 +1436,7 @@
String value = null;
for (int i = 0; i < 20; i++) {
// State transition is done when sys.usb.state is set to the new configuration
- value = SystemProperties.get(USB_STATE_PROPERTY);
+ value = getSystemProperty(USB_STATE_PROPERTY, "");
if (state.equals(value)) return true;
SystemClock.sleep(50);
}
@@ -1432,14 +1451,14 @@
* we always set it due to b/23631400, where adbd was getting killed
* and not restarted due to property timeouts on some devices
*/
- SystemProperties.set(USB_CONFIG_PROPERTY, config);
+ setSystemProperty(USB_CONFIG_PROPERTY, config);
}
@Override
- protected void setEnabledFunctions(String functions, boolean forceRestart,
- boolean usbDataUnlocked) {
+ protected void setEnabledFunctions(long usbFunctions, boolean forceRestart) {
+ boolean usbDataUnlocked = isUsbDataTransferActive(usbFunctions);
if (DEBUG) {
- Slog.d(TAG, "setEnabledFunctions functions=" + functions + ", "
+ Slog.d(TAG, "setEnabledFunctions functions=" + usbFunctions + ", "
+ "forceRestart=" + forceRestart + ", usbDataUnlocked=" + usbDataUnlocked);
}
@@ -1452,9 +1471,9 @@
/**
* Try to set the enabled functions.
*/
- final String oldFunctions = mCurrentFunctions;
+ final long oldFunctions = mCurrentFunctions;
final boolean oldFunctionsApplied = mCurrentFunctionsApplied;
- if (trySetEnabledFunctions(functions, forceRestart)) {
+ if (trySetEnabledFunctions(usbFunctions, forceRestart)) {
return;
}
@@ -1464,7 +1483,7 @@
* user restrictions independently of any other new functions we were
* trying to activate.
*/
- if (oldFunctionsApplied && !oldFunctions.equals(functions)) {
+ if (oldFunctionsApplied && oldFunctions != usbFunctions) {
Slog.e(TAG, "Failsafe 1: Restoring previous USB functions.");
if (trySetEnabledFunctions(oldFunctions, false)) {
return;
@@ -1475,7 +1494,7 @@
* Still didn't work. Try to restore the default functions.
*/
Slog.e(TAG, "Failsafe 2: Restoring default USB functions.");
- if (trySetEnabledFunctions(null, false)) {
+ if (trySetEnabledFunctions(UsbManager.FUNCTION_NONE, false)) {
return;
}
@@ -1484,7 +1503,7 @@
* Try to get ADB working if enabled.
*/
Slog.e(TAG, "Failsafe 3: Restoring empty function list (with ADB if enabled).");
- if (trySetEnabledFunctions(UsbManager.USB_FUNCTION_NONE, false)) {
+ if (trySetEnabledFunctions(UsbManager.FUNCTION_NONE, false)) {
return;
}
@@ -1495,30 +1514,49 @@
}
private boolean isNormalBoot() {
- String bootMode = SystemProperties.get(BOOT_MODE_PROPERTY, "unknown");
+ String bootMode = getSystemProperty(BOOT_MODE_PROPERTY, "unknown");
return bootMode.equals(NORMAL_BOOT) || bootMode.equals("unknown");
}
- private boolean trySetEnabledFunctions(String functions, boolean forceRestart) {
+ protected String applyAdbFunction(String functions) {
+ // Do not pass null pointer to the UsbManager.
+ // There isn't a check there.
+ if (functions == null) {
+ functions = "";
+ }
+ if (mAdbEnabled) {
+ functions = addFunction(functions, UsbManager.USB_FUNCTION_ADB);
+ } else {
+ functions = removeFunction(functions, UsbManager.USB_FUNCTION_ADB);
+ }
+ return functions;
+ }
+
+ private boolean trySetEnabledFunctions(long usbFunctions, boolean forceRestart) {
+ String functions = null;
+ if (usbFunctions != UsbManager.FUNCTION_NONE) {
+ functions = UsbManager.usbFunctionsToString(usbFunctions);
+ }
+ mCurrentFunctions = usbFunctions;
if (functions == null || applyAdbFunction(functions)
.equals(UsbManager.USB_FUNCTION_NONE)) {
- functions = getChargingFunctions();
+ functions = UsbManager.usbFunctionsToString(getChargingFunctions());
}
functions = applyAdbFunction(functions);
String oemFunctions = applyOemOverrideFunction(functions);
- if (!isNormalBoot() && !mCurrentFunctions.equals(functions)) {
- SystemProperties.set(getPersistProp(true), functions);
+ if (!isNormalBoot() && !mCurrentFunctionsStr.equals(functions)) {
+ setSystemProperty(getPersistProp(true), functions);
}
if ((!functions.equals(oemFunctions)
&& !mCurrentOemFunctions.equals(oemFunctions))
- || !mCurrentFunctions.equals(functions)
+ || !mCurrentFunctionsStr.equals(functions)
|| !mCurrentFunctionsApplied
|| forceRestart) {
Slog.i(TAG, "Setting USB config to " + functions);
- mCurrentFunctions = functions;
+ mCurrentFunctionsStr = functions;
mCurrentOemFunctions = oemFunctions;
mCurrentFunctionsApplied = false;
@@ -1538,12 +1576,12 @@
setUsbConfig(oemFunctions);
if (mBootCompleted
- && (UsbManager.containsFunction(functions, UsbManager.USB_FUNCTION_MTP)
- || UsbManager.containsFunction(functions, UsbManager.USB_FUNCTION_PTP))) {
+ && (containsFunction(functions, UsbManager.USB_FUNCTION_MTP)
+ || containsFunction(functions, UsbManager.USB_FUNCTION_PTP))) {
/**
* Start up dependent services.
*/
- updateUsbStateBroadcastIfNeeded(true);
+ updateUsbStateBroadcastIfNeeded(getAppliedFunctions(mCurrentFunctions), true);
}
if (!waitForState(oemFunctions)) {
@@ -1557,7 +1595,7 @@
}
private String getPersistProp(boolean functions) {
- String bootMode = SystemProperties.get(BOOT_MODE_PROPERTY, "unknown");
+ String bootMode = getSystemProperty(BOOT_MODE_PROPERTY, "unknown");
String persistProp = USB_PERSISTENT_CONFIG_PROPERTY;
if (!(bootMode.equals(NORMAL_BOOT) || bootMode.equals("unknown"))) {
if (functions) {
@@ -1568,9 +1606,54 @@
}
return persistProp;
}
+
+ private String addFunction(String functions, String function) {
+ if (UsbManager.USB_FUNCTION_NONE.equals(functions)) {
+ return function;
+ }
+ if (!containsFunction(functions, function)) {
+ if (functions.length() > 0) {
+ functions += ",";
+ }
+ functions += function;
+ }
+ return functions;
+ }
+
+ private String removeFunction(String functions, String function) {
+ String[] split = functions.split(",");
+ for (int i = 0; i < split.length; i++) {
+ if (function.equals(split[i])) {
+ split[i] = null;
+ }
+ }
+ if (split.length == 1 && split[0] == null) {
+ return UsbManager.USB_FUNCTION_NONE;
+ }
+ StringBuilder builder = new StringBuilder();
+ for (int i = 0; i < split.length; i++) {
+ String s = split[i];
+ if (s != null) {
+ if (builder.length() > 0) {
+ builder.append(",");
+ }
+ builder.append(s);
+ }
+ }
+ return builder.toString();
+ }
+
+ private boolean containsFunction(String functions, String function) {
+ int index = functions.indexOf(function);
+ if (index < 0) return false;
+ if (index > 0 && functions.charAt(index - 1) != ',') return false;
+ int charAfter = index + function.length();
+ if (charAfter < functions.length() && functions.charAt(charAfter) != ',') return false;
+ return true;
+ }
}
- private final class UsbHandlerHal extends UsbHandler {
+ private static final class UsbHandlerHal extends UsbHandler {
/**
* Proxy object for the usb gadget hal daemon.
@@ -1627,9 +1710,12 @@
*/
protected static final String ADBD = "adbd";
+ protected boolean mCurrentUsbFunctionsRequested;
- UsbHandlerHal(Looper looper) {
- super(looper);
+ UsbHandlerHal(Looper looper, Context context, UsbDeviceManager deviceManager,
+ UsbDebuggingManager debuggingManager, UsbAlsaManager alsaManager,
+ UsbSettingsManager settingsManager) {
+ super(looper, context, deviceManager, debuggingManager, alsaManager, settingsManager);
try {
ServiceNotification serviceNotification = new ServiceNotification();
@@ -1645,25 +1731,12 @@
mGadgetProxy = IUsbGadget.getService(true);
mGadgetProxy.linkToDeath(new UsbGadgetDeathRecipient(),
USB_GADGET_HAL_DEATH_COOKIE);
- mCurrentFunctions = UsbManager.USB_FUNCTION_NONE;
+ mCurrentFunctions = UsbManager.FUNCTION_NONE;
mGadgetProxy.getCurrentUsbFunctions(new UsbGadgetCallback());
mCurrentUsbFunctionsRequested = true;
}
String state = FileUtils.readTextFile(new File(STATE_PATH), 0, null).trim();
updateState(state);
-
- /**
- * Register observer to listen for settings changes.
- */
- mContentResolver.registerContentObserver(
- Settings.Global.getUriFor(Settings.Global.ADB_ENABLED),
- false, new AdbSettingsObserver());
-
- /**
- * Watch for USB configuration changes.
- */
- mUEventObserver.startObserving(USB_STATE_MATCH);
- mUEventObserver.startObserving(ACCESSORY_START_MATCH);
} catch (NoSuchElementException e) {
Slog.e(TAG, "Usb gadget hal not found", e);
} catch (RemoteException e) {
@@ -1696,7 +1769,7 @@
mGadgetProxy.linkToDeath(new UsbGadgetDeathRecipient(),
USB_GADGET_HAL_DEATH_COOKIE);
if (!mCurrentFunctionsApplied) {
- setCurrentFunctions(mCurrentFunctions, mUsbDataUnlocked);
+ setEnabledFunctions(mCurrentFunctions, false);
}
} catch (NoSuchElementException e) {
Slog.e(TAG, "Usb gadget hal not found", e);
@@ -1711,12 +1784,12 @@
public void handleMessage(Message msg) {
switch (msg.what) {
case MSG_SET_CHARGING_FUNCTIONS:
- setEnabledFunctions(null, false, mUsbDataUnlocked);
+ setEnabledFunctions(UsbManager.FUNCTION_NONE, false);
break;
case MSG_SET_FUNCTIONS_TIMEOUT:
Slog.e(TAG, "Set functions timed out! no reply from usb hal");
if (msg.arg1 != 1) {
- setEnabledFunctions(null, false, mUsbDataUnlocked);
+ setEnabledFunctions(UsbManager.FUNCTION_NONE, false);
}
break;
case MSG_GET_CURRENT_USB_FUNCTIONS:
@@ -1725,7 +1798,8 @@
if (mCurrentUsbFunctionsRequested) {
Slog.e(TAG, "updating mCurrentFunctions");
- mCurrentFunctions = functionListToString((Long) msg.obj);
+ // Mask out adb, since it is stored in mAdbEnabled
+ mCurrentFunctions = ((Long) msg.obj) & ~UsbManager.FUNCTION_ADB;
Slog.e(TAG,
"mCurrentFunctions:" + mCurrentFunctions + "applied:" + msg.arg1);
mCurrentFunctionsApplied = msg.arg1 == 1;
@@ -1737,7 +1811,7 @@
* Dont force to default when the configuration is already set to default.
*/
if (msg.arg1 != 1) {
- setEnabledFunctions(null, !mAdbEnabled, false);
+ setEnabledFunctions(UsbManager.FUNCTION_NONE, !mAdbEnabled);
}
break;
default:
@@ -1789,70 +1863,7 @@
}
}
- private long stringToFunctionList(String config) {
- long functionsMask = 0;
- String[] functions = config.split(",");
- for (int i = 0; i < functions.length; i++) {
- switch (functions[i]) {
- case "none":
- functionsMask |= GadgetFunction.NONE;
- break;
- case "adb":
- functionsMask |= GadgetFunction.ADB;
- break;
- case "mtp":
- functionsMask |= GadgetFunction.MTP;
- break;
- case "ptp":
- functionsMask |= GadgetFunction.PTP;
- break;
- case "midi":
- functionsMask |= GadgetFunction.MIDI;
- break;
- case "accessory":
- functionsMask |= GadgetFunction.ACCESSORY;
- break;
- case "rndis":
- functionsMask |= GadgetFunction.RNDIS;
- break;
- }
- }
- return functionsMask;
- }
-
- private String functionListToString(Long functionList) {
- StringJoiner functions = new StringJoiner(",");
- if (functionList == GadgetFunction.NONE) {
- functions.add("none");
- return functions.toString();
- }
- if ((functionList & GadgetFunction.ADB) != 0) {
- functions.add("adb");
- }
- if ((functionList & GadgetFunction.MTP) != 0) {
- functions.add("mtp");
- }
- if ((functionList & GadgetFunction.PTP) != 0) {
- functions.add("ptp");
- }
- if ((functionList & GadgetFunction.MIDI) != 0) {
- functions.add("midi");
- }
- if ((functionList & GadgetFunction.ACCESSORY) != 0) {
- functions.add("accessory");
- }
- if ((functionList & GadgetFunction.RNDIS) != 0) {
- functions.add("rndis");
- }
- /**
- * Remove the trailing comma.
- */
- return functions.toString();
- }
-
-
- private void setUsbConfig(String config, boolean chargingFunctions) {
- Long functions = stringToFunctionList(config);
+ private void setUsbConfig(long config, boolean chargingFunctions) {
if (true) Slog.d(TAG, "setUsbConfig(" + config + ") request:" + ++mCurrentRequest);
/**
* Cancel any ongoing requests, if present.
@@ -1867,20 +1878,20 @@
return;
}
try {
- if ((functions & GadgetFunction.ADB) != 0) {
+ if ((config & UsbManager.FUNCTION_ADB) != 0) {
/**
* Start adbd if ADB function is included in the configuration.
*/
- SystemProperties.set(CTL_START, ADBD);
+ setSystemProperty(CTL_START, ADBD);
} else {
/**
* Stop adbd otherwise.
*/
- SystemProperties.set(CTL_STOP, ADBD);
+ setSystemProperty(CTL_STOP, ADBD);
}
UsbGadgetCallback usbGadgetCallback = new UsbGadgetCallback(mCurrentRequest,
- functions, chargingFunctions);
- mGadgetProxy.setCurrentUsbFunctions(functions, usbGadgetCallback,
+ config, chargingFunctions);
+ mGadgetProxy.setCurrentUsbFunctions(config, usbGadgetCallback,
SET_FUNCTIONS_TIMEOUT_MS - SET_FUNCTIONS_LEEWAY_MS);
sendMessageDelayed(MSG_SET_FUNCTIONS_TIMEOUT, chargingFunctions,
SET_FUNCTIONS_TIMEOUT_MS);
@@ -1894,49 +1905,29 @@
}
@Override
- protected void setEnabledFunctions(String functions, boolean forceRestart,
- boolean usbDataUnlocked) {
+ protected void setEnabledFunctions(long functions, boolean forceRestart) {
if (DEBUG) {
Slog.d(TAG, "setEnabledFunctions functions=" + functions + ", "
- + "forceRestart=" + forceRestart + ", usbDataUnlocked=" + usbDataUnlocked);
+ + "forceRestart=" + forceRestart);
}
-
- if (usbDataUnlocked != mUsbDataUnlocked) {
- mUsbDataUnlocked = usbDataUnlocked;
- updateUsbNotification(false);
- forceRestart = true;
- }
-
- trySetEnabledFunctions(functions, forceRestart);
- }
-
- private void trySetEnabledFunctions(String functions, boolean forceRestart) {
- boolean chargingFunctions = false;
-
- if (functions == null || applyAdbFunction(functions)
- .equals(UsbManager.USB_FUNCTION_NONE)) {
- functions = getChargingFunctions();
- chargingFunctions = true;
- }
- functions = applyAdbFunction(functions);
-
- if (!mCurrentFunctions.equals(functions)
+ if (mCurrentFunctions != functions
|| !mCurrentFunctionsApplied
|| forceRestart) {
- Slog.i(TAG, "Setting USB config to " + functions);
+ Slog.i(TAG, "Setting USB config to " + UsbManager.usbFunctionsToString(functions));
mCurrentFunctions = functions;
mCurrentFunctionsApplied = false;
// set the flag to false as that would be stale value
mCurrentUsbFunctionsRequested = false;
- // Set the new USB configuration.
- setUsbConfig(mCurrentFunctions, chargingFunctions);
+ boolean chargingFunctions = functions == UsbManager.FUNCTION_NONE;
+ functions = getAppliedFunctions(functions);
- if (mBootCompleted
- && (UsbManager.containsFunction(functions, UsbManager.USB_FUNCTION_MTP)
- || UsbManager.containsFunction(functions, UsbManager.USB_FUNCTION_PTP))) {
+ // Set the new USB configuration.
+ setUsbConfig(functions, chargingFunctions);
+
+ if (mBootCompleted && isUsbDataTransferActive(functions)) {
// Start up dependent services.
- updateUsbStateBroadcastIfNeeded(true);
+ updateUsbStateBroadcastIfNeeded(functions, true);
}
}
}
@@ -1968,27 +1959,37 @@
return nativeOpenAccessory();
}
- /**
- * Checks whether the function is present in the USB configuration.
- *
- * @param function function to be checked.
- */
- public boolean isFunctionEnabled(String function) {
- return mHandler.isFunctionEnabled(function);
+ public long getCurrentFunctions() {
+ return mHandler.getEnabledFunctions();
+ }
+
+ public long getScreenUnlockedFunctions() {
+ return mHandler.getScreenUnlockedFunctions();
}
/**
* Adds function to the current USB configuration.
*
- * @param functions name of the USB function, or null to restore the default function.
- * @param usbDataUnlocked whether user data is accessible.
+ * @param functions The functions to set, or empty to set the charging function.
*/
- public void setCurrentFunctions(String functions, boolean usbDataUnlocked) {
+ public void setCurrentFunctions(long functions) {
if (DEBUG) {
- Slog.d(TAG, "setCurrentFunctions(" + functions + ", "
- + usbDataUnlocked + ")");
+ Slog.d(TAG, "setCurrentFunctions(" + UsbManager.usbFunctionsToString(functions) + ")");
}
- mHandler.sendMessage(MSG_SET_CURRENT_FUNCTIONS, functions, usbDataUnlocked);
+ if (functions == UsbManager.FUNCTION_NONE) {
+ MetricsLogger.action(mContext, MetricsEvent.ACTION_USB_CONFIG_CHARGING);
+ } else if (functions == UsbManager.FUNCTION_MTP) {
+ MetricsLogger.action(mContext, MetricsEvent.ACTION_USB_CONFIG_MTP);
+ } else if (functions == UsbManager.FUNCTION_PTP) {
+ MetricsLogger.action(mContext, MetricsEvent.ACTION_USB_CONFIG_PTP);
+ } else if (functions == UsbManager.FUNCTION_MIDI) {
+ MetricsLogger.action(mContext, MetricsEvent.ACTION_USB_CONFIG_MIDI);
+ } else if (functions == UsbManager.FUNCTION_RNDIS) {
+ MetricsLogger.action(mContext, MetricsEvent.ACTION_USB_CONFIG_RNDIS);
+ } else if (functions == UsbManager.FUNCTION_ACCESSORY) {
+ MetricsLogger.action(mContext, MetricsEvent.ACTION_USB_CONFIG_ACCESSORY);
+ }
+ mHandler.sendMessage(MSG_SET_CURRENT_FUNCTIONS, functions);
}
/**
@@ -1996,9 +1997,10 @@
*
* @param functions Functions to set.
*/
- public void setScreenUnlockedFunctions(String functions) {
+ public void setScreenUnlockedFunctions(long functions) {
if (DEBUG) {
- Slog.d(TAG, "setScreenUnlockedFunctions(" + functions + ")");
+ Slog.d(TAG, "setScreenUnlockedFunctions("
+ + UsbManager.usbFunctionsToString(functions) + ")");
}
mHandler.sendMessage(MSG_SET_SCREEN_UNLOCKED_FUNCTIONS, functions);
}
diff --git a/services/usb/java/com/android/server/usb/UsbService.java b/services/usb/java/com/android/server/usb/UsbService.java
index 1a20819..2f6e531 100644
--- a/services/usb/java/com/android/server/usb/UsbService.java
+++ b/services/usb/java/com/android/server/usb/UsbService.java
@@ -382,59 +382,44 @@
}
@Override
+ public void setCurrentFunctions(long functions) {
+ mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_USB, null);
+ Preconditions.checkArgument(UsbManager.areSettableFunctions(functions));
+ Preconditions.checkState(mDeviceManager != null);
+ mDeviceManager.setCurrentFunctions(functions);
+ }
+
+ @Override
+ public void setCurrentFunction(String functions, boolean usbDataUnlocked) {
+ setCurrentFunctions(UsbManager.usbFunctionsFromString(functions));
+ }
+
+ @Override
public boolean isFunctionEnabled(String function) {
- mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_USB, null);
- return mDeviceManager != null && mDeviceManager.isFunctionEnabled(function);
+ return (getCurrentFunctions() & UsbManager.usbFunctionsFromString(function)) != 0;
}
@Override
- public void setCurrentFunction(String function, boolean usbDataUnlocked) {
+ public long getCurrentFunctions() {
mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_USB, null);
-
- if (!isSupportedCurrentFunction(function)) {
- Slog.w(TAG, "Caller of setCurrentFunction() requested unsupported USB function: "
- + function);
- function = UsbManager.USB_FUNCTION_NONE;
- }
-
- if (mDeviceManager != null) {
- mDeviceManager.setCurrentFunctions(function, usbDataUnlocked);
- } else {
- throw new IllegalStateException("USB device mode not supported");
- }
+ Preconditions.checkState(mDeviceManager != null);
+ return mDeviceManager.getCurrentFunctions();
}
@Override
- public void setScreenUnlockedFunctions(String function) {
+ public void setScreenUnlockedFunctions(long functions) {
mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_USB, null);
+ Preconditions.checkArgument(UsbManager.areSettableFunctions(functions));
+ Preconditions.checkState(mDeviceManager != null);
- if (!isSupportedCurrentFunction(function)) {
- Slog.w(TAG, "Caller of setScreenUnlockedFunctions() requested unsupported USB function:"
- + function);
- function = UsbManager.USB_FUNCTION_NONE;
- }
-
- if (mDeviceManager != null) {
- mDeviceManager.setScreenUnlockedFunctions(function);
- } else {
- throw new IllegalStateException("USB device mode not supported");
- }
+ mDeviceManager.setScreenUnlockedFunctions(functions);
}
- private static boolean isSupportedCurrentFunction(String function) {
- if (function == null) return true;
-
- switch (function) {
- case UsbManager.USB_FUNCTION_NONE:
- case UsbManager.USB_FUNCTION_AUDIO_SOURCE:
- case UsbManager.USB_FUNCTION_MIDI:
- case UsbManager.USB_FUNCTION_MTP:
- case UsbManager.USB_FUNCTION_PTP:
- case UsbManager.USB_FUNCTION_RNDIS:
- return true;
- }
-
- return false;
+ @Override
+ public long getScreenUnlockedFunctions() {
+ mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_USB, null);
+ Preconditions.checkState(mDeviceManager != null);
+ return mDeviceManager.getScreenUnlockedFunctions();
}
@Override
diff --git a/tests/HwAccelerationTest/AndroidManifest.xml b/tests/HwAccelerationTest/AndroidManifest.xml
index ebf5f68..c8f96c9 100644
--- a/tests/HwAccelerationTest/AndroidManifest.xml
+++ b/tests/HwAccelerationTest/AndroidManifest.xml
@@ -285,7 +285,8 @@
<activity
android:name="ColoredShadowsActivity"
- android:label="View/ColoredShadows">
+ android:label="View/ColoredShadows"
+ android:theme="@style/ThemeColoredShadows">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="com.android.test.hwui.TEST" />
diff --git a/tests/HwAccelerationTest/res/values/styles.xml b/tests/HwAccelerationTest/res/values/styles.xml
index 108709b..fa5437f 100644
--- a/tests/HwAccelerationTest/res/values/styles.xml
+++ b/tests/HwAccelerationTest/res/values/styles.xml
@@ -34,4 +34,11 @@
<item name="android:translationZ">400dp</item>
<item name="android:layout_alignParentBottom">true</item>
</style>
+
+ <style name="ThemeColoredShadows" parent="@android:style/Theme.Material.Light">
+ <!--
+ <item name="android:ambientShadowAlpha">0</item>
+ <item name="android:spotShadowAlpha">1</item>
+ -->
+ </style>
</resources>
diff --git a/tests/HwAccelerationTest/src/com/android/test/hwui/ColoredShadowsActivity.java b/tests/HwAccelerationTest/src/com/android/test/hwui/ColoredShadowsActivity.java
index 135c93c..901d90e 100644
--- a/tests/HwAccelerationTest/src/com/android/test/hwui/ColoredShadowsActivity.java
+++ b/tests/HwAccelerationTest/src/com/android/test/hwui/ColoredShadowsActivity.java
@@ -17,6 +17,9 @@
package com.android.test.hwui;
import android.app.Activity;
+import android.graphics.Color;
+import android.graphics.PixelFormat;
+import android.graphics.drawable.ColorDrawable;
import android.os.Bundle;
import android.view.View;
import android.view.ViewGroup;
@@ -36,7 +39,9 @@
private void setShadowColors(ViewGroup row, int rowIndex) {
for (int i = 0; i < row.getChildCount(); i++) {
View view = row.getChildAt(i);
- view.setShadowColor(shadowColorFor(view));
+ //view.setBackground(new MyHackyBackground());
+ view.setOutlineSpotShadowColor(shadowColorFor(view));
+ view.setOutlineAmbientShadowColor(shadowColorFor(view));
view.setElevation(6.0f * (rowIndex + 1));
}
}
@@ -44,12 +49,27 @@
private int shadowColorFor(View view) {
switch (view.getId()) {
case R.id.grey: return 0xFF3C4043;
- case R.id.blue: return 0xFF185ABC;
- case R.id.red: return 0xFFB31412;
- case R.id.yellow: return 0xFFEA8600;
- case R.id.green: return 0xFF137333;
+ case R.id.blue: return Color.BLUE;
+ case R.id.red: return 0xFFEA4335;
+ case R.id.yellow: return 0xFFFBBC04;
+ case R.id.green: return 0xFF34A853;
default: return 0xFF000000;
}
}
+ private static class MyHackyBackground extends ColorDrawable {
+ MyHackyBackground() {
+ super(0);
+ }
+
+ @Override
+ public int getOpacity() {
+ return PixelFormat.TRANSLUCENT;
+ }
+
+ @Override
+ public int getAlpha() {
+ return 254;
+ }
+ }
}
diff --git a/tests/UsbTests/Android.mk b/tests/UsbTests/Android.mk
new file mode 100644
index 0000000..a04f32a
--- /dev/null
+++ b/tests/UsbTests/Android.mk
@@ -0,0 +1,44 @@
+#
+# Copyright (C) 2018 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.
+#
+
+LOCAL_PATH:= $(call my-dir)
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_TAGS := tests
+
+LOCAL_SRC_FILES := $(call all-subdir-java-files)
+
+LOCAL_STATIC_JAVA_LIBRARIES := \
+ frameworks-base-testutils \
+ android-support-test \
+ mockito-target-inline-minus-junit4 \
+ platform-test-annotations \
+ services.core \
+ services.net \
+ services.usb \
+ truth-prebuilt \
+
+LOCAL_JNI_SHARED_LIBRARIES := \
+ libdexmakerjvmtiagent \
+
+LOCAL_CERTIFICATE := platform
+
+LOCAL_PACKAGE_NAME := UsbTests
+
+LOCAL_COMPATIBILITY_SUITE := device-tests
+
+include $(BUILD_PACKAGE)
diff --git a/tests/UsbTests/AndroidManifest.xml b/tests/UsbTests/AndroidManifest.xml
new file mode 100644
index 0000000..5d60695
--- /dev/null
+++ b/tests/UsbTests/AndroidManifest.xml
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2018 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.
+-->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="com.android.server.usb" >
+
+ <uses-permission android:name="android.permission.INTERACT_ACROSS_USERS" />
+ <uses-permission android:name="android.permission.MANAGE_USERS" />
+
+ <application android:debuggable="true">
+ <uses-library android:name="android.test.runner" />
+ </application>
+
+ <instrumentation android:name="android.support.test.runner.AndroidJUnitRunner"
+ android:targetPackage="com.android.server.usb"
+ android:label="UsbTests"/>
+</manifest>
diff --git a/tests/UsbTests/AndroidTest.xml b/tests/UsbTests/AndroidTest.xml
new file mode 100644
index 0000000..0b623fb
--- /dev/null
+++ b/tests/UsbTests/AndroidTest.xml
@@ -0,0 +1,29 @@
+<!-- Copyright (C) 2018 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.
+-->
+<configuration description="Runs sample instrumentation test.">
+ <target_preparer class="com.android.tradefed.targetprep.TestFilePushSetup"/>
+ <target_preparer class="com.android.tradefed.targetprep.TestAppInstallSetup">
+ <option name="test-file-name" value="UsbTests.apk"/>
+ </target_preparer>
+ <target_preparer class="com.android.tradefed.targetprep.PushFilePreparer"/>
+ <target_preparer class="com.android.tradefed.targetprep.RunCommandTargetPreparer"/>
+ <option name="test-suite-tag" value="apct"/>
+ <option name="test-tag" value="UsbTests"/>
+
+ <test class="com.android.tradefed.testtype.AndroidJUnitTest">
+ <option name="package" value="com.android.server.usb"/>
+ <option name="runner" value="android.support.test.runner.AndroidJUnitRunner"/>
+ </test>
+</configuration>
\ No newline at end of file
diff --git a/tests/UsbTests/src/com/android/server/usb/UsbHandlerTest.java b/tests/UsbTests/src/com/android/server/usb/UsbHandlerTest.java
new file mode 100644
index 0000000..c491b46
--- /dev/null
+++ b/tests/UsbTests/src/com/android/server/usb/UsbHandlerTest.java
@@ -0,0 +1,316 @@
+/*
+ * Copyright (C) 2018 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.usb;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotEquals;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import android.content.ContentResolver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.SharedPreferences;
+import android.hardware.usb.UsbManager;
+import android.os.Handler;
+import android.os.Looper;
+import android.os.UserHandle;
+import android.provider.Settings;
+import android.support.test.InstrumentationRegistry;
+import android.support.test.filters.SmallTest;
+import android.support.test.runner.AndroidJUnit4;
+
+import com.android.server.FgThread;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
+import java.util.HashMap;
+import java.util.Locale;
+import java.util.Map;
+
+/**
+ * Tests for UsbHandler state changes.
+ */
+@RunWith(AndroidJUnit4.class)
+public class UsbHandlerTest {
+ private static final String TAG = UsbHandlerTest.class.getSimpleName();
+
+ @Mock
+ private UsbDeviceManager mUsbDeviceManager;
+ @Mock
+ private UsbDebuggingManager mUsbDebuggingManager;
+ @Mock
+ private UsbAlsaManager mUsbAlsaManager;
+ @Mock
+ private UsbSettingsManager mUsbSettingsManager;
+ @Mock
+ private SharedPreferences mSharedPreferences;
+ @Mock
+ private SharedPreferences.Editor mEditor;
+
+ private MockUsbHandler mUsbHandler;
+
+ private static final int MSG_UPDATE_STATE = 0;
+ private static final int MSG_ENABLE_ADB = 1;
+ private static final int MSG_SET_CURRENT_FUNCTIONS = 2;
+ private static final int MSG_SYSTEM_READY = 3;
+ private static final int MSG_BOOT_COMPLETED = 4;
+ private static final int MSG_USER_SWITCHED = 5;
+ private static final int MSG_UPDATE_USER_RESTRICTIONS = 6;
+ private static final int MSG_SET_SCREEN_UNLOCKED_FUNCTIONS = 12;
+ private static final int MSG_UPDATE_SCREEN_LOCK = 13;
+
+ private Map<String, String> mMockProperties;
+ private Map<String, Integer> mMockGlobalSettings;
+
+ private class MockUsbHandler extends UsbDeviceManager.UsbHandler {
+ boolean mIsUsbTransferAllowed;
+ Intent mBroadcastedIntent;
+
+ MockUsbHandler(Looper looper, Context context, UsbDeviceManager deviceManager,
+ UsbDebuggingManager debuggingManager, UsbAlsaManager alsaManager,
+ UsbSettingsManager settingsManager) {
+ super(looper, context, deviceManager, debuggingManager, alsaManager, settingsManager);
+ mUseUsbNotification = false;
+ mIsUsbTransferAllowed = true;
+ mCurrentUsbFunctionsReceived = true;
+ }
+
+ @Override
+ protected void setEnabledFunctions(long functions, boolean force) {
+ mCurrentFunctions = functions;
+ }
+
+ @Override
+ protected void setSystemProperty(String property, String value) {
+ mMockProperties.put(property, value);
+ }
+
+ @Override
+ protected void putGlobalSettings(ContentResolver resolver, String setting, int val) {
+ mMockGlobalSettings.put(setting, val);
+ }
+
+ @Override
+ protected String getSystemProperty(String property, String def) {
+ if (mMockProperties.containsKey(property)) {
+ return mMockProperties.get(property);
+ }
+ return def;
+ }
+
+ @Override
+ protected boolean isUsbTransferAllowed() {
+ return mIsUsbTransferAllowed;
+ }
+
+ @Override
+ protected SharedPreferences getPinnedSharedPrefs(Context context) {
+ return mSharedPreferences;
+ }
+
+ @Override
+ protected void sendStickyBroadcast(Intent intent) {
+ mBroadcastedIntent = intent;
+ }
+ }
+
+ @Before
+ public void before() {
+ MockitoAnnotations.initMocks(this);
+ mMockProperties = new HashMap<>();
+ mMockGlobalSettings = new HashMap<>();
+ when(mSharedPreferences.edit()).thenReturn(mEditor);
+
+ mUsbHandler = new MockUsbHandler(FgThread.get().getLooper(),
+ InstrumentationRegistry.getContext(), mUsbDeviceManager, mUsbDebuggingManager,
+ mUsbAlsaManager, mUsbSettingsManager);
+ }
+
+ @SmallTest
+ public void setFunctionsMtp() {
+ mUsbHandler.handleMessage(mUsbHandler.obtainMessage(MSG_SET_CURRENT_FUNCTIONS,
+ UsbManager.FUNCTION_MTP));
+ assertNotEquals(mUsbHandler.getEnabledFunctions() & UsbManager.FUNCTION_MTP, 0);
+ }
+
+ @SmallTest
+ public void setFunctionsPtp() {
+ mUsbHandler.handleMessage(mUsbHandler.obtainMessage(MSG_SET_CURRENT_FUNCTIONS,
+ UsbManager.FUNCTION_PTP));
+ assertNotEquals(mUsbHandler.getEnabledFunctions() & UsbManager.FUNCTION_PTP, 0);
+ }
+
+ @SmallTest
+ public void setFunctionsMidi() {
+ mUsbHandler.handleMessage(mUsbHandler.obtainMessage(MSG_SET_CURRENT_FUNCTIONS,
+ UsbManager.FUNCTION_MIDI));
+ assertNotEquals(mUsbHandler.getEnabledFunctions() & UsbManager.FUNCTION_MIDI, 0);
+ }
+
+ @SmallTest
+ public void setFunctionsRndis() {
+ mUsbHandler.handleMessage(mUsbHandler.obtainMessage(MSG_SET_CURRENT_FUNCTIONS,
+ UsbManager.FUNCTION_RNDIS));
+ assertNotEquals(mUsbHandler.getEnabledFunctions() & UsbManager.FUNCTION_RNDIS, 0);
+ }
+
+ @SmallTest
+ public void enableAdb() {
+ sendBootCompleteMessages(mUsbHandler);
+ mUsbHandler.handleMessage(mUsbHandler.obtainMessage(MSG_ENABLE_ADB, 1));
+ assertEquals(mUsbHandler.getEnabledFunctions(), UsbManager.FUNCTION_NONE);
+ assertTrue(mUsbHandler.mAdbEnabled);
+ assertEquals(mMockProperties.get(UsbDeviceManager.UsbHandler
+ .USB_PERSISTENT_CONFIG_PROPERTY), UsbManager.USB_FUNCTION_ADB);
+ verify(mUsbDebuggingManager).setAdbEnabled(true);
+
+ mUsbHandler.handleMessage(mUsbHandler.obtainMessage(MSG_UPDATE_STATE, 1, 1));
+
+ assertTrue(mUsbHandler.mBroadcastedIntent.getBooleanExtra(UsbManager.USB_CONNECTED, false));
+ assertTrue(mUsbHandler.mBroadcastedIntent
+ .getBooleanExtra(UsbManager.USB_CONFIGURED, false));
+ assertTrue(mUsbHandler.mBroadcastedIntent
+ .getBooleanExtra(UsbManager.USB_FUNCTION_ADB, false));
+ }
+
+ @SmallTest
+ public void disableAdb() {
+ mMockProperties.put(UsbDeviceManager.UsbHandler.USB_PERSISTENT_CONFIG_PROPERTY,
+ UsbManager.USB_FUNCTION_ADB);
+ mUsbHandler = new MockUsbHandler(FgThread.get().getLooper(),
+ InstrumentationRegistry.getContext(), mUsbDeviceManager, mUsbDebuggingManager,
+ mUsbAlsaManager, mUsbSettingsManager);
+
+ sendBootCompleteMessages(mUsbHandler);
+ mUsbHandler.handleMessage(mUsbHandler.obtainMessage(MSG_ENABLE_ADB, 0));
+ assertEquals(mUsbHandler.getEnabledFunctions(), UsbManager.FUNCTION_NONE);
+ assertFalse(mUsbHandler.mAdbEnabled);
+ assertEquals(mMockProperties.get(UsbDeviceManager.UsbHandler
+ .USB_PERSISTENT_CONFIG_PROPERTY), "");
+ verify(mUsbDebuggingManager).setAdbEnabled(false);
+ }
+
+ @SmallTest
+ public void bootCompletedCharging() {
+ sendBootCompleteMessages(mUsbHandler);
+ assertEquals(mUsbHandler.getEnabledFunctions(), UsbManager.FUNCTION_NONE);
+ }
+
+ @Test
+ @SmallTest
+ public void bootCompletedAdbEnabled() {
+ mMockProperties.put(UsbDeviceManager.UsbHandler.USB_PERSISTENT_CONFIG_PROPERTY, "adb");
+ mUsbHandler = new MockUsbHandler(FgThread.get().getLooper(),
+ InstrumentationRegistry.getContext(), mUsbDeviceManager, mUsbDebuggingManager,
+ mUsbAlsaManager, mUsbSettingsManager);
+
+ sendBootCompleteMessages(mUsbHandler);
+ assertEquals(mUsbHandler.getEnabledFunctions(), UsbManager.FUNCTION_NONE);
+ assertEquals(mMockGlobalSettings.get(Settings.Global.ADB_ENABLED).intValue(), 1);
+ assertTrue(mUsbHandler.mAdbEnabled);
+ verify(mUsbDebuggingManager).setAdbEnabled(true);
+ }
+
+ @SmallTest
+ public void userSwitchedDisablesMtp() {
+ mUsbHandler.handleMessage(mUsbHandler.obtainMessage(MSG_SET_CURRENT_FUNCTIONS,
+ UsbManager.FUNCTION_MTP));
+ assertNotEquals(mUsbHandler.getEnabledFunctions() & UsbManager.FUNCTION_MTP, 0);
+
+ mUsbHandler.handleMessage(mUsbHandler.obtainMessage(MSG_USER_SWITCHED,
+ UserHandle.getCallingUserId() + 1));
+ assertEquals(mUsbHandler.getEnabledFunctions(), UsbManager.FUNCTION_NONE);
+ }
+
+ @SmallTest
+ public void changedRestrictionsDisablesMtp() {
+ mUsbHandler.handleMessage(mUsbHandler.obtainMessage(MSG_SET_CURRENT_FUNCTIONS,
+ UsbManager.FUNCTION_MTP));
+ assertNotEquals(mUsbHandler.getEnabledFunctions() & UsbManager.FUNCTION_MTP, 0);
+
+ mUsbHandler.mIsUsbTransferAllowed = false;
+ mUsbHandler.handleMessage(mUsbHandler.obtainMessage(MSG_UPDATE_USER_RESTRICTIONS));
+ assertEquals(mUsbHandler.getEnabledFunctions(), UsbManager.FUNCTION_NONE);
+ }
+
+ @SmallTest
+ public void disconnectResetsCharging() {
+ sendBootCompleteMessages(mUsbHandler);
+
+ mUsbHandler.handleMessage(mUsbHandler.obtainMessage(MSG_SET_CURRENT_FUNCTIONS,
+ UsbManager.FUNCTION_MTP));
+ assertNotEquals(mUsbHandler.getEnabledFunctions() & UsbManager.FUNCTION_MTP, 0);
+
+ mUsbHandler.handleMessage(mUsbHandler.obtainMessage(MSG_UPDATE_STATE, 0, 0));
+
+ assertEquals(mUsbHandler.getEnabledFunctions(), UsbManager.FUNCTION_NONE);
+ }
+
+ @SmallTest
+ public void configuredSendsBroadcast() {
+ sendBootCompleteMessages(mUsbHandler);
+ mUsbHandler.handleMessage(mUsbHandler.obtainMessage(MSG_SET_CURRENT_FUNCTIONS,
+ UsbManager.FUNCTION_MTP));
+ assertNotEquals(mUsbHandler.getEnabledFunctions() & UsbManager.FUNCTION_MTP, 0);
+
+ mUsbHandler.handleMessage(mUsbHandler.obtainMessage(MSG_UPDATE_STATE, 1, 1));
+
+ assertNotEquals(mUsbHandler.getEnabledFunctions() & UsbManager.FUNCTION_MTP, 0);
+ assertTrue(mUsbHandler.mBroadcastedIntent.getBooleanExtra(UsbManager.USB_CONNECTED, false));
+ assertTrue(mUsbHandler.mBroadcastedIntent
+ .getBooleanExtra(UsbManager.USB_CONFIGURED, false));
+ assertTrue(mUsbHandler.mBroadcastedIntent
+ .getBooleanExtra(UsbManager.USB_FUNCTION_MTP, false));
+ }
+
+ @SmallTest
+ public void setScreenUnlockedFunctions() {
+ sendBootCompleteMessages(mUsbHandler);
+ mUsbHandler.handleMessage(mUsbHandler.obtainMessage(MSG_UPDATE_SCREEN_LOCK, 0));
+
+ mUsbHandler.handleMessage(mUsbHandler.obtainMessage(MSG_SET_SCREEN_UNLOCKED_FUNCTIONS,
+ UsbManager.FUNCTION_MTP));
+ assertNotEquals(mUsbHandler.getScreenUnlockedFunctions() & UsbManager.FUNCTION_MTP, 0);
+ assertNotEquals(mUsbHandler.getEnabledFunctions() & UsbManager.FUNCTION_MTP, 0);
+ verify(mEditor).putString(String.format(Locale.ENGLISH,
+ UsbDeviceManager.UNLOCKED_CONFIG_PREF, mUsbHandler.mCurrentUser),
+ UsbManager.USB_FUNCTION_MTP);
+ }
+
+ @SmallTest
+ public void unlockScreen() {
+ when(mSharedPreferences.getString(String.format(Locale.ENGLISH,
+ UsbDeviceManager.UNLOCKED_CONFIG_PREF, mUsbHandler.mCurrentUser), ""))
+ .thenReturn(UsbManager.USB_FUNCTION_MTP);
+ sendBootCompleteMessages(mUsbHandler);
+ mUsbHandler.handleMessage(mUsbHandler.obtainMessage(MSG_UPDATE_SCREEN_LOCK, 0));
+
+ assertNotEquals(mUsbHandler.getScreenUnlockedFunctions() & UsbManager.FUNCTION_MTP, 0);
+ assertNotEquals(mUsbHandler.getEnabledFunctions() & UsbManager.FUNCTION_MTP, 0);
+ }
+
+ private static void sendBootCompleteMessages(Handler handler) {
+ handler.handleMessage(handler.obtainMessage(MSG_BOOT_COMPLETED));
+ handler.handleMessage(handler.obtainMessage(MSG_SYSTEM_READY));
+ }
+}
\ No newline at end of file
diff --git a/tests/net/java/com/android/server/connectivity/TetheringTest.java b/tests/net/java/com/android/server/connectivity/TetheringTest.java
index 099cfd4..e692652 100644
--- a/tests/net/java/com/android/server/connectivity/TetheringTest.java
+++ b/tests/net/java/com/android/server/connectivity/TetheringTest.java
@@ -311,7 +311,7 @@
// Emulate pressing the USB tethering button in Settings UI.
mTethering.startTethering(TETHERING_USB, null, false);
mLooper.dispatchAll();
- verify(mUsbManager, times(1)).setCurrentFunction(UsbManager.USB_FUNCTION_RNDIS, false);
+ verify(mUsbManager, times(1)).setCurrentFunctions(UsbManager.FUNCTION_RNDIS);
// Pretend we receive a USB connected broadcast. Here we also pretend
// that the RNDIS function is somehow enabled, so that we see if we