Merge "Importance slider logging." into nyc-dev
diff --git a/api/current.txt b/api/current.txt
index 649d7fa..40ead48 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -198,7 +198,6 @@
public static final class R.attr {
ctor public R.attr();
- field public static final int abiOverride = 16844054; // 0x1010516
field public static final int absListViewStyle = 16842858; // 0x101006a
field public static final int accessibilityEventTypes = 16843648; // 0x1010380
field public static final int accessibilityFeedbackType = 16843650; // 0x1010382
@@ -1365,6 +1364,7 @@
field public static final deprecated int unfocusedMonthDateColor = 16843588; // 0x1010344
field public static final int unselectedAlpha = 16843278; // 0x101020e
field public static final int updatePeriodMillis = 16843344; // 0x1010250
+ field public static final int use32bitAbi = 16844054; // 0x1010516
field public static final int useDefaultMargins = 16843641; // 0x1010379
field public static final int useIntrinsicSizeAsMinimum = 16843536; // 0x1010310
field public static final int useLevel = 16843167; // 0x101019f
@@ -40661,6 +40661,21 @@
method public static android.view.FocusFinder getInstance();
}
+ public final class FrameMetrics {
+ ctor public FrameMetrics(android.view.FrameMetrics);
+ method public long getMetric(int);
+ field public static final int ANIMATION_DURATION = 2; // 0x2
+ field public static final int COMMAND_ISSUE_DURATION = 6; // 0x6
+ field public static final int DRAW_DURATION = 4; // 0x4
+ field public static final int FIRST_DRAW_FRAME = 9; // 0x9
+ field public static final int INPUT_HANDLING_DURATION = 1; // 0x1
+ field public static final int LAYOUT_MEASURE_DURATION = 3; // 0x3
+ field public static final int SWAP_BUFFERS_DURATION = 7; // 0x7
+ field public static final int SYNC_DURATION = 5; // 0x5
+ field public static final int TOTAL_DURATION = 8; // 0x8
+ field public static final int UNKNOWN_DELAY_DURATION = 0; // 0x0
+ }
+
public abstract class FrameStats {
ctor public FrameStats();
method public final long getEndTimeNano();
@@ -43164,6 +43179,7 @@
ctor public Window(android.content.Context);
method public abstract void addContentView(android.view.View, android.view.ViewGroup.LayoutParams);
method public void addFlags(int);
+ method public final void addFrameMetricsListener(android.view.Window.FrameMetricsListener, android.os.Handler);
method public void clearFlags(int);
method public abstract void closeAllPanels();
method public abstract void closePanel(int);
@@ -43215,6 +43231,7 @@
method public abstract boolean performContextMenuIdentifierAction(int, int);
method public abstract boolean performPanelIdentifierAction(int, int, int);
method public abstract boolean performPanelShortcut(int, int, android.view.KeyEvent, int);
+ method public final void removeFrameMetricsListener(android.view.Window.FrameMetricsListener);
method public boolean requestFeature(int);
method public abstract void restoreHierarchyState(android.os.Bundle);
method public abstract android.os.Bundle saveHierarchyState();
@@ -43340,6 +43357,10 @@
method public abstract android.view.ActionMode onWindowStartingActionMode(android.view.ActionMode.Callback, int);
}
+ public static abstract interface Window.FrameMetricsListener {
+ method public abstract void onMetricsAvailable(android.view.Window, android.view.FrameMetrics, int);
+ }
+
public static abstract interface Window.OnRestrictedCaptionAreaChangedListener {
method public abstract void onRestrictedCaptionAreaChanged(android.graphics.Rect);
}
diff --git a/api/system-current.txt b/api/system-current.txt
index 3c3054e..dfe1e08 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -293,7 +293,6 @@
public static final class R.attr {
ctor public R.attr();
- field public static final int abiOverride = 16844054; // 0x1010516
field public static final int absListViewStyle = 16842858; // 0x101006a
field public static final int accessibilityEventTypes = 16843648; // 0x1010380
field public static final int accessibilityFeedbackType = 16843650; // 0x1010382
@@ -1464,6 +1463,7 @@
field public static final deprecated int unfocusedMonthDateColor = 16843588; // 0x1010344
field public static final int unselectedAlpha = 16843278; // 0x101020e
field public static final int updatePeriodMillis = 16843344; // 0x1010250
+ field public static final int use32bitAbi = 16844054; // 0x1010516
field public static final int useDefaultMargins = 16843641; // 0x1010379
field public static final int useIntrinsicSizeAsMinimum = 16843536; // 0x1010310
field public static final int useLevel = 16843167; // 0x101019f
@@ -43413,6 +43413,21 @@
method public static android.view.FocusFinder getInstance();
}
+ public final class FrameMetrics {
+ ctor public FrameMetrics(android.view.FrameMetrics);
+ method public long getMetric(int);
+ field public static final int ANIMATION_DURATION = 2; // 0x2
+ field public static final int COMMAND_ISSUE_DURATION = 6; // 0x6
+ field public static final int DRAW_DURATION = 4; // 0x4
+ field public static final int FIRST_DRAW_FRAME = 9; // 0x9
+ field public static final int INPUT_HANDLING_DURATION = 1; // 0x1
+ field public static final int LAYOUT_MEASURE_DURATION = 3; // 0x3
+ field public static final int SWAP_BUFFERS_DURATION = 7; // 0x7
+ field public static final int SYNC_DURATION = 5; // 0x5
+ field public static final int TOTAL_DURATION = 8; // 0x8
+ field public static final int UNKNOWN_DELAY_DURATION = 0; // 0x0
+ }
+
public abstract class FrameStats {
ctor public FrameStats();
method public final long getEndTimeNano();
@@ -45916,6 +45931,7 @@
ctor public Window(android.content.Context);
method public abstract void addContentView(android.view.View, android.view.ViewGroup.LayoutParams);
method public void addFlags(int);
+ method public final void addFrameMetricsListener(android.view.Window.FrameMetricsListener, android.os.Handler);
method public void clearFlags(int);
method public abstract void closeAllPanels();
method public abstract void closePanel(int);
@@ -45967,6 +45983,7 @@
method public abstract boolean performContextMenuIdentifierAction(int, int);
method public abstract boolean performPanelIdentifierAction(int, int, int);
method public abstract boolean performPanelShortcut(int, int, android.view.KeyEvent, int);
+ method public final void removeFrameMetricsListener(android.view.Window.FrameMetricsListener);
method public boolean requestFeature(int);
method public abstract void restoreHierarchyState(android.os.Bundle);
method public abstract android.os.Bundle saveHierarchyState();
@@ -46093,6 +46110,10 @@
method public abstract android.view.ActionMode onWindowStartingActionMode(android.view.ActionMode.Callback, int);
}
+ public static abstract interface Window.FrameMetricsListener {
+ method public abstract void onMetricsAvailable(android.view.Window, android.view.FrameMetrics, int);
+ }
+
public static abstract interface Window.OnRestrictedCaptionAreaChangedListener {
method public abstract void onRestrictedCaptionAreaChanged(android.graphics.Rect);
}
diff --git a/api/test-current.txt b/api/test-current.txt
index 8fbcff9..10733f9 100644
--- a/api/test-current.txt
+++ b/api/test-current.txt
@@ -198,7 +198,6 @@
public static final class R.attr {
ctor public R.attr();
- field public static final int abiOverride = 16844054; // 0x1010516
field public static final int absListViewStyle = 16842858; // 0x101006a
field public static final int accessibilityEventTypes = 16843648; // 0x1010380
field public static final int accessibilityFeedbackType = 16843650; // 0x1010382
@@ -1365,6 +1364,7 @@
field public static final deprecated int unfocusedMonthDateColor = 16843588; // 0x1010344
field public static final int unselectedAlpha = 16843278; // 0x101020e
field public static final int updatePeriodMillis = 16843344; // 0x1010250
+ field public static final int use32bitAbi = 16844054; // 0x1010516
field public static final int useDefaultMargins = 16843641; // 0x1010379
field public static final int useIntrinsicSizeAsMinimum = 16843536; // 0x1010310
field public static final int useLevel = 16843167; // 0x101019f
@@ -40678,6 +40678,21 @@
method public static android.view.FocusFinder getInstance();
}
+ public final class FrameMetrics {
+ ctor public FrameMetrics(android.view.FrameMetrics);
+ method public long getMetric(int);
+ field public static final int ANIMATION_DURATION = 2; // 0x2
+ field public static final int COMMAND_ISSUE_DURATION = 6; // 0x6
+ field public static final int DRAW_DURATION = 4; // 0x4
+ field public static final int FIRST_DRAW_FRAME = 9; // 0x9
+ field public static final int INPUT_HANDLING_DURATION = 1; // 0x1
+ field public static final int LAYOUT_MEASURE_DURATION = 3; // 0x3
+ field public static final int SWAP_BUFFERS_DURATION = 7; // 0x7
+ field public static final int SYNC_DURATION = 5; // 0x5
+ field public static final int TOTAL_DURATION = 8; // 0x8
+ field public static final int UNKNOWN_DELAY_DURATION = 0; // 0x0
+ }
+
public abstract class FrameStats {
ctor public FrameStats();
method public final long getEndTimeNano();
@@ -43181,6 +43196,7 @@
ctor public Window(android.content.Context);
method public abstract void addContentView(android.view.View, android.view.ViewGroup.LayoutParams);
method public void addFlags(int);
+ method public final void addFrameMetricsListener(android.view.Window.FrameMetricsListener, android.os.Handler);
method public void clearFlags(int);
method public abstract void closeAllPanels();
method public abstract void closePanel(int);
@@ -43232,6 +43248,7 @@
method public abstract boolean performContextMenuIdentifierAction(int, int);
method public abstract boolean performPanelIdentifierAction(int, int, int);
method public abstract boolean performPanelShortcut(int, int, android.view.KeyEvent, int);
+ method public final void removeFrameMetricsListener(android.view.Window.FrameMetricsListener);
method public boolean requestFeature(int);
method public abstract void restoreHierarchyState(android.os.Bundle);
method public abstract android.os.Bundle saveHierarchyState();
@@ -43357,6 +43374,10 @@
method public abstract android.view.ActionMode onWindowStartingActionMode(android.view.ActionMode.Callback, int);
}
+ public static abstract interface Window.FrameMetricsListener {
+ method public abstract void onMetricsAvailable(android.view.Window, android.view.FrameMetrics, int);
+ }
+
public static abstract interface Window.OnRestrictedCaptionAreaChangedListener {
method public abstract void onRestrictedCaptionAreaChanged(android.graphics.Rect);
}
diff --git a/core/java/android/content/pm/PackageParser.java b/core/java/android/content/pm/PackageParser.java
index 72ace15..5dddebd 100644
--- a/core/java/android/content/pm/PackageParser.java
+++ b/core/java/android/content/pm/PackageParser.java
@@ -337,7 +337,7 @@
public final boolean coreApp;
public final boolean multiArch;
- public final String abiOverride;
+ public final boolean use32bitAbi;
public final boolean extractNativeLibs;
public PackageLite(String codePath, ApkLite baseApk, String[] splitNames,
@@ -354,7 +354,7 @@
this.splitRevisionCodes = splitRevisionCodes;
this.coreApp = baseApk.coreApp;
this.multiArch = baseApk.multiArch;
- this.abiOverride = baseApk.abiOverride;
+ this.use32bitAbi = baseApk.use32bitAbi;
this.extractNativeLibs = baseApk.extractNativeLibs;
}
@@ -382,12 +382,12 @@
public final Signature[] signatures;
public final boolean coreApp;
public final boolean multiArch;
- public final String abiOverride;
+ public final boolean use32bitAbi;
public final boolean extractNativeLibs;
public ApkLite(String codePath, String packageName, String splitName, int versionCode,
int revisionCode, int installLocation, List<VerifierInfo> verifiers,
- Signature[] signatures, boolean coreApp, boolean multiArch, String abiOverride,
+ Signature[] signatures, boolean coreApp, boolean multiArch, boolean use32bitAbi,
boolean extractNativeLibs) {
this.codePath = codePath;
this.packageName = packageName;
@@ -399,7 +399,7 @@
this.signatures = signatures;
this.coreApp = coreApp;
this.multiArch = multiArch;
- this.abiOverride = abiOverride;
+ this.use32bitAbi = use32bitAbi;
this.extractNativeLibs = extractNativeLibs;
}
}
@@ -843,8 +843,7 @@
}
pkg.setCodePath(packageDir.getAbsolutePath());
- pkg.setCpuAbiOverride(lite.abiOverride);
-
+ pkg.setUse32bitAbi(lite.use32bitAbi);
return pkg;
} finally {
IoUtils.closeQuietly(assets);
@@ -875,7 +874,7 @@
try {
final Package pkg = parseBaseApk(apkFile, assets, flags);
pkg.setCodePath(apkFile.getAbsolutePath());
- pkg.setCpuAbiOverride(lite.abiOverride);
+ pkg.setUse32bitAbi(lite.use32bitAbi);
return pkg;
} finally {
IoUtils.closeQuietly(assets);
@@ -1380,7 +1379,7 @@
int revisionCode = 0;
boolean coreApp = false;
boolean multiArch = false;
- String abiOverride = null;
+ boolean use32bitAbi = false;
boolean extractNativeLibs = true;
for (int i = 0; i < attrs.getAttributeCount(); i++) {
@@ -1421,8 +1420,8 @@
if ("multiArch".equals(attr)) {
multiArch = attrs.getAttributeBooleanValue(i, false);
}
- if ("abiOverride".equals(attr)) {
- abiOverride = attrs.getAttributeValue(i);
+ if ("use32bitAbi".equals(attr)) {
+ use32bitAbi = attrs.getAttributeBooleanValue(i, false);
}
if ("extractNativeLibs".equals(attr)) {
extractNativeLibs = attrs.getAttributeBooleanValue(i, true);
@@ -1433,7 +1432,7 @@
return new ApkLite(codePath, packageSplit.first, packageSplit.second, versionCode,
revisionCode, installLocation, verifiers, signatures, coreApp, multiArch,
- abiOverride, extractNativeLibs);
+ use32bitAbi, extractNativeLibs);
}
/**
@@ -4740,6 +4739,12 @@
* and prods fields out of {@code this.applicationInfo}.
*/
public String cpuAbiOverride;
+ /**
+ * The install time abi override to choose 32bit abi's when multiple abi's
+ * are present. This is only meaningfull for multiarch applications.
+ * The use32bitAbi attribute is ignored if cpuAbiOverride is also set.
+ */
+ public boolean use32bitAbi;
public Package(String packageName) {
this.packageName = packageName;
@@ -4872,12 +4877,12 @@
}
}
- public void setCpuAbiOverride(String cpuAbiOverride) {
- this.cpuAbiOverride = cpuAbiOverride;
+ public void setUse32bitAbi(boolean use32bitAbi) {
+ this.use32bitAbi = use32bitAbi;
if (childPackages != null) {
final int packageCount = childPackages.size();
for (int i = 0; i < packageCount; i++) {
- childPackages.get(i).cpuAbiOverride = cpuAbiOverride;
+ childPackages.get(i).use32bitAbi = use32bitAbi;
}
}
}
diff --git a/core/java/android/view/FrameMetrics.java b/core/java/android/view/FrameMetrics.java
new file mode 100644
index 0000000..8e66f86
--- /dev/null
+++ b/core/java/android/view/FrameMetrics.java
@@ -0,0 +1,281 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.view;
+
+import android.annotation.IntDef;
+import android.view.Window;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
+/**
+ * Class containing timing data for various milestones in a frame
+ * lifecycle reported by the rendering subsystem.
+ * <p>
+ * Supported metrics can be queried via their corresponding identifier.
+ * </p>
+ */
+public final class FrameMetrics {
+
+ /**
+ * Metric identifier for unknown delay.
+ * <p>
+ * Represents the number of nanoseconds elapsed waiting for the
+ * UI thread to become responsive and process the frame. This
+ * should be 0 most of the time.
+ * </p>
+ */
+ public static final int UNKNOWN_DELAY_DURATION = 0;
+
+ /**
+ * Metric identifier for input handling duration.
+ * <p>
+ * Represents the number of nanoseconds elapsed issuing
+ * input handling callbacks.
+ * </p>
+ */
+ public static final int INPUT_HANDLING_DURATION = 1;
+
+ /**
+ * Metric identifier for animation callback duration.
+ * <p>
+ * Represents the number of nanoseconds elapsed issuing
+ * animation callbacks.
+ * </p>
+ */
+ public static final int ANIMATION_DURATION = 2;
+
+ /**
+ * Metric identifier for layout/measure duration.
+ * <p>
+ * Represents the number of nanoseconds elapsed measuring
+ * and laying out the invalidated pieces of the view hierarchy.
+ * </p>
+ */
+ public static final int LAYOUT_MEASURE_DURATION = 3;
+ /**
+ * Metric identifier for draw duration.
+ * <p>
+ * Represents the number of nanoseconds elapsed computing
+ * DisplayLists for transformations applied to the view
+ * hierarchy.
+ * </p>
+ */
+ public static final int DRAW_DURATION = 4;
+
+ /**
+ * Metric identifier for sync duration.
+ * <p>
+ * Represents the number of nanoseconds elapsed
+ * synchronizing the computed display lists with the render
+ * thread.
+ * </p>
+ */
+ public static final int SYNC_DURATION = 5;
+
+ /**
+ * Metric identifier for command issue duration.
+ * <p>
+ * Represents the number of nanoseconds elapsed
+ * issuing draw commands to the GPU.
+ * </p>
+ */
+ public static final int COMMAND_ISSUE_DURATION = 6;
+
+ /**
+ * Metric identifier for swap buffers duration.
+ * <p>
+ * Represents the number of nanoseconds elapsed issuing
+ * the frame buffer for this frame to the display
+ * subsystem.
+ * </p>
+ */
+ public static final int SWAP_BUFFERS_DURATION = 7;
+
+ /**
+ * Metric identifier for total frame duration.
+ * <p>
+ * Represents the total time in nanoseconds this frame took to render
+ * and be issued to the display subsystem.
+ * </p>
+ * <p>
+ * Equal to the sum of the values of all other time-valued metric
+ * identifiers.
+ * </p>
+ */
+ public static final int TOTAL_DURATION = 8;
+
+ /**
+ * Metric identifier for a boolean value determining whether this frame was
+ * the first to draw in a new Window layout.
+ * <p>
+ * {@link #getMetric(int)} will return 0 for false, 1 for true.
+ * </p>
+ * <p>
+ * First draw frames are expected to be slow and should usually be exempt
+ * from display jank calculations as they do not cause skips in animations
+ * and are usually hidden by window animations or other tricks.
+ * </p>
+ */
+ public static final int FIRST_DRAW_FRAME = 9;
+
+ private static final int FRAME_INFO_FLAG_FIRST_DRAW = 1 << 0;
+
+ /**
+ * Identifiers for metrics available for each frame.
+ *
+ * {@see {@link #getMetric(int)}}
+ * @hide
+ */
+ @IntDef({
+ UNKNOWN_DELAY_DURATION,
+ INPUT_HANDLING_DURATION,
+ ANIMATION_DURATION,
+ LAYOUT_MEASURE_DURATION,
+ DRAW_DURATION,
+ SYNC_DURATION,
+ COMMAND_ISSUE_DURATION,
+ SWAP_BUFFERS_DURATION,
+ TOTAL_DURATION,
+ FIRST_DRAW_FRAME,
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface Metric {}
+
+ /**
+ * Timestamp indices for frame milestones.
+ *
+ * May change from release to release.
+ *
+ * Must be kept in sync with frameworks/base/libs/hwui/FrameInfo.h.
+ *
+ * @hide
+ */
+ @IntDef ({
+ Index.FLAGS,
+ Index.INTENDED_VSYNC,
+ Index.VSYNC,
+ Index.OLDEST_INPUT_EVENT,
+ Index.NEWEST_INPUT_EVENT,
+ Index.HANDLE_INPUT_START,
+ Index.ANIMATION_START,
+ Index.PERFORM_TRAVERSALS_START,
+ Index.DRAW_START,
+ Index.SYNC_QUEUED,
+ Index.SYNC_START,
+ Index.ISSUE_DRAW_COMMANDS_START,
+ Index.SWAP_BUFFERS,
+ Index.FRAME_COMPLETED,
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ private @interface Index {
+ int FLAGS = 0;
+ int INTENDED_VSYNC = 1;
+ int VSYNC = 2;
+ int OLDEST_INPUT_EVENT = 3;
+ int NEWEST_INPUT_EVENT = 4;
+ int HANDLE_INPUT_START = 5;
+ int ANIMATION_START = 6;
+ int PERFORM_TRAVERSALS_START = 7;
+ int DRAW_START = 8;
+ int SYNC_QUEUED = 9;
+ int SYNC_START = 10;
+ int ISSUE_DRAW_COMMANDS_START = 11;
+ int SWAP_BUFFERS = 12;
+ int FRAME_COMPLETED = 13;
+
+ int FRAME_STATS_COUNT = 14; // must always be last
+ }
+
+ /*
+ * Bucket endpoints for each Metric defined above.
+ *
+ * Each defined metric *must* have a corresponding entry
+ * in this list.
+ */
+ private static final int[] DURATIONS = new int[] {
+ // UNKNOWN_DELAY
+ Index.INTENDED_VSYNC, Index.HANDLE_INPUT_START,
+ // INPUT_HANDLING
+ Index.HANDLE_INPUT_START, Index.ANIMATION_START,
+ // ANIMATION
+ Index.ANIMATION_START, Index.PERFORM_TRAVERSALS_START,
+ // LAYOUT_MEASURE
+ Index.PERFORM_TRAVERSALS_START, Index.DRAW_START,
+ // DRAW
+ Index.DRAW_START, Index.SYNC_QUEUED,
+ // SYNC
+ Index.SYNC_START, Index.ISSUE_DRAW_COMMANDS_START,
+ // COMMAND_ISSUE
+ Index.ISSUE_DRAW_COMMANDS_START, Index.SWAP_BUFFERS,
+ // SWAP_BUFFERS
+ Index.SWAP_BUFFERS, Index.FRAME_COMPLETED,
+ // TOTAL_DURATION
+ Index.INTENDED_VSYNC, Index.FRAME_COMPLETED,
+ };
+
+ /* package */ final long[] mTimingData;
+
+ /**
+ * Constructs a FrameMetrics object as a copy.
+ * <p>
+ * Use this method to copy out metrics reported by
+ * {@link Window.FrameMetricsListener#onMetricsAvailable(Window, FrameMetrics, int)}
+ * </p>
+ * @param other the FrameMetrics object to copy.
+ */
+ public FrameMetrics(FrameMetrics other) {
+ mTimingData = new long[Index.FRAME_STATS_COUNT];
+ System.arraycopy(other.mTimingData, 0, mTimingData, 0, mTimingData.length);
+ }
+
+ /**
+ * @hide
+ */
+ FrameMetrics() {
+ mTimingData = new long[Index.FRAME_STATS_COUNT];
+ }
+
+ /**
+ * Retrieves the value associated with Metric identifier {@code id}
+ * for this frame.
+ * <p>
+ * Boolean metrics are represented in [0,1], with 0 corresponding to
+ * false, and 1 corresponding to true.
+ * </p>
+ * @param id the metric to retrieve
+ * @return the value of the metric or -1 if it is not available.
+ */
+ public long getMetric(@Metric int id) {
+ if (id < UNKNOWN_DELAY_DURATION || id > FIRST_DRAW_FRAME) {
+ return -1;
+ }
+
+ if (mTimingData == null) {
+ return -1;
+ }
+
+ if (id == FIRST_DRAW_FRAME) {
+ return (mTimingData[Index.FLAGS] & FRAME_INFO_FLAG_FIRST_DRAW) != 0 ? 1 : 0;
+ }
+
+ int durationsIdx = 2 * id;
+ return mTimingData[DURATIONS[durationsIdx + 1]]
+ - mTimingData[DURATIONS[durationsIdx]];
+ }
+}
+
diff --git a/core/java/android/view/FrameMetricsObserver.java b/core/java/android/view/FrameMetricsObserver.java
new file mode 100644
index 0000000..f38f8b7
--- /dev/null
+++ b/core/java/android/view/FrameMetricsObserver.java
@@ -0,0 +1,75 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.view;
+
+import android.annotation.NonNull;
+import android.util.Log;
+import android.os.Looper;
+import android.os.MessageQueue;
+
+import com.android.internal.util.VirtualRefBasePtr;
+
+import java.lang.NullPointerException;
+import java.lang.ref.WeakReference;
+import java.lang.SuppressWarnings;
+
+/**
+ * Provides streaming access to frame stats information from the rendering
+ * subsystem to apps.
+ *
+ * @hide
+ */
+public class FrameMetricsObserver {
+ private MessageQueue mMessageQueue;
+
+ private WeakReference<Window> mWindow;
+
+ private FrameMetrics mFrameMetrics;
+
+ /* package */ Window.FrameMetricsListener mListener;
+ /* package */ VirtualRefBasePtr mNative;
+
+ /**
+ * Creates a FrameMetricsObserver
+ *
+ * @param looper the looper to use when invoking callbacks
+ */
+ FrameMetricsObserver(@NonNull Window window, @NonNull Looper looper,
+ @NonNull Window.FrameMetricsListener listener) {
+ if (looper == null) {
+ throw new NullPointerException("looper cannot be null");
+ }
+
+ mMessageQueue = looper.getQueue();
+ if (mMessageQueue == null) {
+ throw new IllegalStateException("invalid looper, null message queue\n");
+ }
+
+ mFrameMetrics = new FrameMetrics();
+ mWindow = new WeakReference<>(window);
+ mListener = listener;
+ }
+
+ // Called by native on the provided Handler
+ @SuppressWarnings("unused")
+ private void notifyDataAvailable(int dropCount) {
+ final Window window = mWindow.get();
+ if (window != null) {
+ mListener.onMetricsAvailable(window, mFrameMetrics, dropCount);
+ }
+ }
+}
diff --git a/core/java/android/view/FrameStatsObserver.java b/core/java/android/view/FrameStatsObserver.java
deleted file mode 100644
index 0add607..0000000
--- a/core/java/android/view/FrameStatsObserver.java
+++ /dev/null
@@ -1,122 +0,0 @@
-/*
- * Copyright (C) 2016 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.view;
-
-import android.annotation.NonNull;
-import android.util.Log;
-import android.os.Looper;
-import android.os.MessageQueue;
-
-import com.android.internal.util.VirtualRefBasePtr;
-
-import java.lang.NullPointerException;
-import java.lang.ref.WeakReference;
-import java.lang.SuppressWarnings;
-
-/**
- * Provides streaming access to frame stats information from the rendering
- * subsystem to apps.
- *
- * @hide
- */
-public abstract class FrameStatsObserver {
- private static final String TAG = "FrameStatsObserver";
-
- private MessageQueue mMessageQueue;
- private long[] mBuffer;
-
- private FrameStats mFrameStats;
-
- /* package */ ThreadedRenderer mRenderer;
- /* package */ VirtualRefBasePtr mNative;
-
- /**
- * Containing class for frame statistics reported
- * by the rendering subsystem.
- */
- public static class FrameStats {
- /**
- * Precise timing data for various milestones in a frame
- * lifecycle.
- *
- * This data is exactly the same as what is returned by
- * `adb shell dumpsys gfxinfo <PACKAGE_NAME> framestats`
- *
- * The fields reported may change from release to release.
- *
- * @see {@link http://developer.android.com/training/testing/performance.html}
- * for a description of the fields present.
- */
- public long[] mTimingData;
- }
-
- /**
- * Creates a FrameStatsObserver
- *
- * @param looper the looper to use when invoking callbacks
- */
- public FrameStatsObserver(@NonNull Looper looper) {
- if (looper == null) {
- throw new NullPointerException("looper cannot be null");
- }
-
- mMessageQueue = looper.getQueue();
- if (mMessageQueue == null) {
- throw new IllegalStateException("invalid looper, null message queue\n");
- }
-
- mFrameStats = new FrameStats();
- }
-
- /**
- * Called on provided looper when frame stats data is available
- * for the previous frame.
- *
- * Clients of this class must do as little work as possible within
- * this callback, as the buffer is shared between the producer and consumer.
- *
- * If the consumer is still executing within this method when there is new
- * data available that data will be dropped. The producer cannot
- * wait on the consumer.
- *
- * @param data the newly available data
- */
- public abstract void onDataAvailable(FrameStats data);
-
- /**
- * Returns the number of reports dropped as a result of a slow
- * consumer.
- */
- public long getDroppedReportCount() {
- if (mRenderer == null) {
- return 0;
- }
-
- return mRenderer.getDroppedFrameReportCount();
- }
-
- public boolean isRegistered() {
- return mRenderer != null && mNative != null;
- }
-
- // === called by native === //
- @SuppressWarnings("unused")
- private void notifyDataAvailable() {
- mFrameStats.mTimingData = mBuffer;
- onDataAvailable(mFrameStats);
- }
-}
diff --git a/core/java/android/view/ThreadedRenderer.java b/core/java/android/view/ThreadedRenderer.java
index 8b06ecf..ca41d78 100644
--- a/core/java/android/view/ThreadedRenderer.java
+++ b/core/java/android/view/ThreadedRenderer.java
@@ -354,8 +354,6 @@
private boolean mEnabled;
private boolean mRequested = true;
- private HashSet<FrameStatsObserver> mFrameStatsObservers;
-
ThreadedRenderer(Context context, boolean translucent) {
final TypedArray a = context.obtainStyledAttributes(null, R.styleable.Lighting, 0, 0);
mLightY = a.getDimension(R.styleable.Lighting_lightY, 0);
@@ -964,29 +962,14 @@
}
}
- void addFrameStatsObserver(FrameStatsObserver fso) {
- if (mFrameStatsObservers == null) {
- mFrameStatsObservers = new HashSet<>();
- }
-
- long nativeFso = nAddFrameStatsObserver(mNativeProxy, fso);
- fso.mRenderer = this;
- fso.mNative = new VirtualRefBasePtr(nativeFso);
- mFrameStatsObservers.add(fso);
+ void addFrameMetricsObserver(FrameMetricsObserver observer) {
+ long nativeObserver = nAddFrameMetricsObserver(mNativeProxy, observer);
+ observer.mNative = new VirtualRefBasePtr(nativeObserver);
}
- void removeFrameStatsObserver(FrameStatsObserver fso) {
- if (!mFrameStatsObservers.remove(fso)) {
- throw new IllegalArgumentException("attempt to remove FrameStatsObserver that was never added");
- }
-
- nRemoveFrameStatsObserver(mNativeProxy, fso.mNative.get());
- fso.mRenderer = null;
- fso.mNative = null;
- }
-
- long getDroppedFrameReportCount() {
- return nGetDroppedFrameReportCount(mNativeProxy);
+ void removeFrameMetricsObserver(FrameMetricsObserver observer) {
+ nRemoveFrameMetricsObserver(mNativeProxy, observer.mNative.get());
+ observer.mNative = null;
}
static native void setupShadersDiskCache(String cacheFile);
@@ -1044,7 +1027,6 @@
private static native void nSetContentDrawBounds(long nativeProxy, int left,
int top, int right, int bottom);
- private static native long nAddFrameStatsObserver(long nativeProxy, FrameStatsObserver fso);
- private static native void nRemoveFrameStatsObserver(long nativeProxy, long nativeFso);
- private static native long nGetDroppedFrameReportCount(long nativeProxy);
+ private static native long nAddFrameMetricsObserver(long nativeProxy, FrameMetricsObserver observer);
+ private static native void nRemoveFrameMetricsObserver(long nativeProxy, long nativeObserver);
}
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index f52b2907..2612ab2 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -3703,9 +3703,9 @@
private ViewPropertyAnimator mAnimator = null;
/**
- * List of FrameStatsObservers pending registration when mAttachInfo is null.
+ * List of registered FrameMetricsObservers.
*/
- private ArrayList<FrameStatsObserver> mPendingFrameStatsObservers;
+ private ArrayList<FrameMetricsObserver> mFrameMetricsObservers;
/**
* Flag indicating that a drag can cross window boundaries. When
@@ -5479,19 +5479,29 @@
*
* @hide
*/
- public void addFrameStatsObserver(FrameStatsObserver fso) {
+ public void addFrameMetricsListener(Window window, Window.FrameMetricsListener listener,
+ Handler handler) {
if (mAttachInfo != null) {
if (mAttachInfo.mHardwareRenderer != null) {
- mAttachInfo.mHardwareRenderer.addFrameStatsObserver(fso);
+ if (mFrameMetricsObservers == null) {
+ mFrameMetricsObservers = new ArrayList<>();
+ }
+
+ FrameMetricsObserver fmo = new FrameMetricsObserver(window,
+ handler.getLooper(), listener);
+ mFrameMetricsObservers.add(fmo);
+ mAttachInfo.mHardwareRenderer.addFrameMetricsObserver(fmo);
} else {
Log.w(VIEW_LOG_TAG, "View not hardware-accelerated. Unable to observe frame stats");
}
} else {
- if (mPendingFrameStatsObservers == null) {
- mPendingFrameStatsObservers = new ArrayList<>();
+ if (mFrameMetricsObservers == null) {
+ mFrameMetricsObservers = new ArrayList<>();
}
- mPendingFrameStatsObservers.add(fso);
+ FrameMetricsObserver fmo = new FrameMetricsObserver(window,
+ handler.getLooper(), listener);
+ mFrameMetricsObservers.add(fmo);
}
}
@@ -5500,32 +5510,45 @@
*
* @hide
*/
- public void removeFrameStatsObserver(FrameStatsObserver fso) {
+ public void removeFrameMetricsListener(Window.FrameMetricsListener listener) {
ThreadedRenderer renderer = getHardwareRenderer();
-
- if (mPendingFrameStatsObservers != null) {
- mPendingFrameStatsObservers.remove(fso);
+ FrameMetricsObserver fmo = findFrameMetricsObserver(listener);
+ if (fmo == null) {
+ throw new IllegalArgumentException("attempt to remove FrameMetricsListener that was never added");
}
- if (renderer != null) {
- renderer.removeFrameStatsObserver(fso);
+ if (mFrameMetricsObservers != null) {
+ mFrameMetricsObservers.remove(fmo);
+ if (renderer != null) {
+ renderer.removeFrameMetricsObserver(fmo);
+ }
}
}
- private void registerPendingFrameStatsObservers() {
- if (mPendingFrameStatsObservers != null) {
+ private void registerPendingFrameMetricsObservers() {
+ if (mFrameMetricsObservers != null) {
ThreadedRenderer renderer = getHardwareRenderer();
if (renderer != null) {
- for (FrameStatsObserver fso : mPendingFrameStatsObservers) {
- renderer.addFrameStatsObserver(fso);
+ for (FrameMetricsObserver fmo : mFrameMetricsObservers) {
+ renderer.addFrameMetricsObserver(fmo);
}
} else {
Log.w(VIEW_LOG_TAG, "View not hardware-accelerated. Unable to observe frame stats");
}
- mPendingFrameStatsObservers = null;
}
}
+ private FrameMetricsObserver findFrameMetricsObserver(Window.FrameMetricsListener listener) {
+ for (int i = 0; i < mFrameMetricsObservers.size(); i++) {
+ FrameMetricsObserver observer = mFrameMetricsObservers.get(i);
+ if (observer.mListener == listener) {
+ return observer;
+ }
+ }
+
+ return null;
+ }
+
/**
* Call this view's OnClickListener, if it is defined. Performs all normal
* actions associated with clicking: reporting accessibility event, playing
@@ -15160,7 +15183,7 @@
mFloatingTreeObserver = null;
}
- registerPendingFrameStatsObservers();
+ registerPendingFrameMetricsObservers();
if ((mPrivateFlags&PFLAG_SCROLL_CONTAINER) != 0) {
mAttachInfo.mScrollContainers.add(this);
diff --git a/core/java/android/view/Window.java b/core/java/android/view/Window.java
index c68a740..9f05990 100644
--- a/core/java/android/view/Window.java
+++ b/core/java/android/view/Window.java
@@ -34,6 +34,7 @@
import android.media.session.MediaController;
import android.net.Uri;
import android.os.Bundle;
+import android.os.Handler;
import android.os.IBinder;
import android.os.RemoteException;
import android.os.SystemProperties;
@@ -604,6 +605,34 @@
void onRestrictedCaptionAreaChanged(Rect rect);
}
+ /**
+ * Callback for clients that want frame timing information for each
+ * frame rendered by the Window.
+ */
+ public interface FrameMetricsListener {
+ /**
+ * Called when information is available for the previously rendered frame.
+ *
+ * Reports can be dropped if this callback takes too
+ * long to execute, as the report producer cannot wait for the consumer to
+ * complete.
+ *
+ * It is highly recommended that clients copy the passed in FrameMetrics
+ * via {@link FrameMetrics#FrameMetrics(FrameMetrics)} within this method and defer
+ * additional computation or storage to another thread to avoid unnecessarily
+ * dropping reports.
+ *
+ * @param window The {@link Window} on which the frame was displayed.
+ * @param frameMetrics the available metrics. This object is reused on every call
+ * and thus <strong>this reference is not valid outside the scope of this method</strong>.
+ * @param dropCountSinceLastInvocation the number of reports dropped since the last time
+ * this callback was invoked.
+ */
+ void onMetricsAvailable(Window window, FrameMetrics frameMetrics,
+ int dropCountSinceLastInvocation);
+ }
+
+
public Window(Context context) {
mContext = context;
mFeatures = mLocalFeatures = getDefaultFeatures(context);
@@ -798,33 +827,28 @@
* Set an observer to collect frame stats for each frame rendererd in this window.
*
* Must be in hardware rendering mode.
- * @hide
*/
- public final void addFrameStatsObserver(@NonNull FrameStatsObserver fso) {
+ public final void addFrameMetricsListener(@NonNull FrameMetricsListener listener,
+ Handler handler) {
final View decorView = getDecorView();
if (decorView == null) {
throw new IllegalStateException("can't observe a Window without an attached view");
}
- if (fso == null) {
- throw new NullPointerException("FrameStatsObserver cannot be null");
+ if (listener == null) {
+ throw new NullPointerException("listener cannot be null");
}
- if (fso.isRegistered()) {
- throw new IllegalStateException("FrameStatsObserver already registered on a Window.");
- }
-
- decorView.addFrameStatsObserver(fso);
+ decorView.addFrameMetricsListener(this, listener, handler);
}
/**
* Remove observer and stop listening to frame stats for this window.
- * @hide
*/
- public final void removeFrameStatsObserver(FrameStatsObserver fso) {
+ public final void removeFrameMetricsListener(FrameMetricsListener listener) {
final View decorView = getDecorView();
if (decorView != null) {
- getDecorView().removeFrameStatsObserver(fso);
+ getDecorView().removeFrameMetricsListener(listener);
}
}
diff --git a/core/java/android/view/inputmethod/InputMethodInfo.java b/core/java/android/view/inputmethod/InputMethodInfo.java
index 43306d0..ec2c05e 100644
--- a/core/java/android/view/inputmethod/InputMethodInfo.java
+++ b/core/java/android/view/inputmethod/InputMethodInfo.java
@@ -38,7 +38,6 @@
import android.util.Slog;
import android.util.Xml;
import android.view.inputmethod.InputMethodSubtype.InputMethodSubtypeBuilder;
-import android.view.inputmethod.InputMethodSubtypeArray;
import java.io.IOException;
import java.util.ArrayList;
@@ -122,7 +121,7 @@
* @param context The Context in which we are parsing the input method.
* @param service The ResolveInfo returned from the package manager about
* this input method's component.
- * @param additionalSubtypes additional subtypes being added to this InputMethodInfo
+ * @param additionalSubtypesMap additional subtypes being added to this InputMethodInfo
* @hide
*/
public InputMethodInfo(Context context, ResolveInfo service,
@@ -429,12 +428,31 @@
}
}
+ /**
+ * @return {@code true} if the IME is marked to be Encryption-Aware.
+ * @hide
+ */
+ public boolean isEncryptionAware() {
+ if (mService == null || mService.serviceInfo == null ||
+ mService.serviceInfo.applicationInfo == null) {
+ return false;
+ }
+ return mService.serviceInfo.applicationInfo.isEncryptionAware();
+ }
+
public void dump(Printer pw, String prefix) {
pw.println(prefix + "mId=" + mId
+ " mSettingsActivityName=" + mSettingsActivityName
+ " mSupportsSwitchingToNextInputMethod=" + mSupportsSwitchingToNextInputMethod);
pw.println(prefix + "mIsDefaultResId=0x"
+ Integer.toHexString(mIsDefaultResId));
+ if (mService != null && mService.serviceInfo != null &&
+ mService.serviceInfo.applicationInfo != null) {
+ pw.println(" encryptionAware=" +
+ mService.serviceInfo.applicationInfo.isEncryptionAware());
+ } else {
+ pw.println(" encryptionAware=unknown");
+ }
pw.println(prefix + "Service:");
mService.dump(pw, prefix + " ");
}
diff --git a/core/jni/android_view_ThreadedRenderer.cpp b/core/jni/android_view_ThreadedRenderer.cpp
index acd0501..dd0e456 100644
--- a/core/jni/android_view_ThreadedRenderer.cpp
+++ b/core/jni/android_view_ThreadedRenderer.cpp
@@ -41,6 +41,7 @@
#include <Animator.h>
#include <AnimationContext.h>
#include <FrameInfo.h>
+#include <FrameMetricsObserver.h>
#include <IContextFactory.h>
#include <JankTracker.h>
#include <RenderNode.h>
@@ -56,10 +57,11 @@
using namespace android::uirenderer::renderthread;
struct {
- jfieldID buffer;
+ jfieldID frameMetrics;
+ jfieldID timingDataBuffer;
jfieldID messageQueue;
- jmethodID notifyData;
-} gFrameStatsObserverClassInfo;
+ jmethodID callback;
+} gFrameMetricsObserverClassInfo;
static JNIEnv* getenv(JavaVM* vm) {
JNIEnv* env;
@@ -239,31 +241,46 @@
mBuffer = buffer;
}
+ void setDropCount(int dropCount) {
+ mDropCount = dropCount;
+ }
+
virtual void handleMessage(const Message& message);
private:
JavaVM* mVm;
sp<ObserverProxy> mObserver;
- BufferPool::Buffer* mBuffer;
+ BufferPool::Buffer* mBuffer = nullptr;
+ int mDropCount = 0;
};
-class ObserverProxy : public FrameStatsObserver {
+static jlongArray get_metrics_buffer(JNIEnv* env, jobject observer) {
+ jobject frameMetrics = env->GetObjectField(
+ observer, gFrameMetricsObserverClassInfo.frameMetrics);
+ LOG_ALWAYS_FATAL_IF(frameMetrics == nullptr, "unable to retrieve data sink object");
+ jobject buffer = env->GetObjectField(
+ frameMetrics, gFrameMetricsObserverClassInfo.timingDataBuffer);
+ LOG_ALWAYS_FATAL_IF(buffer == nullptr, "unable to retrieve data sink buffer");
+ return reinterpret_cast<jlongArray>(buffer);
+}
+
+class ObserverProxy : public FrameMetricsObserver {
public:
- ObserverProxy(JavaVM *vm, jobject fso) : mVm(vm) {
+ ObserverProxy(JavaVM *vm, jobject observer) : mVm(vm) {
JNIEnv* env = getenv(mVm);
- jlongArray longArrayLocal = env->NewLongArray(kBufferSize);
- LOG_ALWAYS_FATAL_IF(longArrayLocal == nullptr,
- "OOM: can't allocate frame stats buffer");
- env->SetObjectField(fso, gFrameStatsObserverClassInfo.buffer, longArrayLocal);
-
- mFsoWeak = env->NewWeakGlobalRef(fso);
- LOG_ALWAYS_FATAL_IF(mFsoWeak == nullptr,
+ mObserverWeak = env->NewWeakGlobalRef(observer);
+ LOG_ALWAYS_FATAL_IF(mObserverWeak == nullptr,
"unable to create frame stats observer reference");
- jobject messageQueueLocal =
- env->GetObjectField(fso, gFrameStatsObserverClassInfo.messageQueue);
+ jlongArray buffer = get_metrics_buffer(env, observer);
+ jsize bufferSize = env->GetArrayLength(reinterpret_cast<jarray>(buffer));
+ LOG_ALWAYS_FATAL_IF(bufferSize != kBufferSize,
+ "Mismatched Java/Native FrameMetrics data format.");
+
+ jobject messageQueueLocal = env->GetObjectField(
+ observer, gFrameMetricsObserverClassInfo.messageQueue);
mMessageQueue = android_os_MessageQueue_getMessageQueue(env, messageQueueLocal);
LOG_ALWAYS_FATAL_IF(mMessageQueue == nullptr, "message queue not available");
@@ -274,17 +291,18 @@
~ObserverProxy() {
JNIEnv* env = getenv(mVm);
- env->DeleteWeakGlobalRef(mFsoWeak);
+ env->DeleteWeakGlobalRef(mObserverWeak);
}
- jweak getJavaObjectRef() {
- return mFsoWeak;
+ jweak getObserverReference() {
+ return mObserverWeak;
}
- virtual void notify(BufferPool::Buffer* buffer) {
+ virtual void notify(BufferPool::Buffer* buffer, int dropCount) {
buffer->incRef();
mMessageHandler->setBuffer(buffer);
mMessageHandler->setObserver(this);
+ mMessageHandler->setDropCount(dropCount);
mMessageQueue->getLooper()->sendMessage(mMessageHandler, mMessage);
}
@@ -292,26 +310,27 @@
static const int kBufferSize = static_cast<int>(FrameInfoIndex::NumIndexes);
JavaVM* mVm;
- jweak mFsoWeak;
+ jweak mObserverWeak;
+ jobject mJavaBufferGlobal;
sp<MessageQueue> mMessageQueue;
sp<NotifyHandler> mMessageHandler;
Message mMessage;
+
};
void NotifyHandler::handleMessage(const Message& message) {
JNIEnv* env = getenv(mVm);
- jobject target = env->NewLocalRef(mObserver->getJavaObjectRef());
+ jobject target = env->NewLocalRef(mObserver->getObserverReference());
if (target != nullptr) {
- jobject javaBuffer = env->GetObjectField(target, gFrameStatsObserverClassInfo.buffer);
- if (javaBuffer != nullptr) {
- env->SetLongArrayRegion(reinterpret_cast<jlongArray>(javaBuffer),
- 0, mBuffer->getSize(), mBuffer->getBuffer());
- env->CallVoidMethod(target, gFrameStatsObserverClassInfo.notifyData);
- env->DeleteLocalRef(target);
- }
+ jlongArray javaBuffer = get_metrics_buffer(env, target);
+ env->SetLongArrayRegion(javaBuffer,
+ 0, mBuffer->getSize(), mBuffer->getBuffer());
+ env->CallVoidMethod(target, gFrameMetricsObserverClassInfo.callback,
+ mDropCount);
+ env->DeleteLocalRef(target);
}
mBuffer->release();
@@ -579,10 +598,10 @@
}
// ----------------------------------------------------------------------------
-// FrameStatsObserver
+// FrameMetricsObserver
// ----------------------------------------------------------------------------
-static jlong android_view_ThreadedRenderer_addFrameStatsObserver(JNIEnv* env,
+static jlong android_view_ThreadedRenderer_addFrameMetricsObserver(JNIEnv* env,
jclass clazz, jlong proxyPtr, jobject fso) {
JavaVM* vm = nullptr;
if (env->GetJavaVM(&vm) != JNI_OK) {
@@ -593,25 +612,18 @@
renderthread::RenderProxy* renderProxy =
reinterpret_cast<renderthread::RenderProxy*>(proxyPtr);
- FrameStatsObserver* observer = new ObserverProxy(vm, fso);
- renderProxy->addFrameStatsObserver(observer);
+ FrameMetricsObserver* observer = new ObserverProxy(vm, fso);
+ renderProxy->addFrameMetricsObserver(observer);
return reinterpret_cast<jlong>(observer);
}
-static void android_view_ThreadedRenderer_removeFrameStatsObserver(JNIEnv* env, jclass clazz,
+static void android_view_ThreadedRenderer_removeFrameMetricsObserver(JNIEnv* env, jclass clazz,
jlong proxyPtr, jlong observerPtr) {
- FrameStatsObserver* observer = reinterpret_cast<FrameStatsObserver*>(observerPtr);
+ FrameMetricsObserver* observer = reinterpret_cast<FrameMetricsObserver*>(observerPtr);
renderthread::RenderProxy* renderProxy =
reinterpret_cast<renderthread::RenderProxy*>(proxyPtr);
- renderProxy->removeFrameStatsObserver(observer);
-}
-
-static jint android_view_ThreadedRenderer_getDroppedFrameReportCount(JNIEnv* env, jclass clazz,
- jlong proxyPtr) {
- renderthread::RenderProxy* renderProxy =
- reinterpret_cast<renderthread::RenderProxy*>(proxyPtr);
- return renderProxy->getDroppedFrameReportCount();
+ renderProxy->removeFrameMetricsObserver(observer);
}
// ----------------------------------------------------------------------------
@@ -684,25 +696,26 @@
{ "nRemoveRenderNode", "(JJ)V", (void*) android_view_ThreadedRenderer_removeRenderNode},
{ "nDrawRenderNode", "(JJ)V", (void*) android_view_ThreadedRendererd_drawRenderNode},
{ "nSetContentDrawBounds", "(JIIII)V", (void*)android_view_ThreadedRenderer_setContentDrawBounds},
- { "nAddFrameStatsObserver",
- "(JLandroid/view/FrameStatsObserver;)J",
- (void*)android_view_ThreadedRenderer_addFrameStatsObserver },
- { "nRemoveFrameStatsObserver",
+ { "nAddFrameMetricsObserver",
+ "(JLandroid/view/FrameMetricsObserver;)J",
+ (void*)android_view_ThreadedRenderer_addFrameMetricsObserver },
+ { "nRemoveFrameMetricsObserver",
"(JJ)V",
- (void*)android_view_ThreadedRenderer_removeFrameStatsObserver },
- { "nGetDroppedFrameReportCount",
- "(J)J",
- (void*)android_view_ThreadedRenderer_getDroppedFrameReportCount },
+ (void*)android_view_ThreadedRenderer_removeFrameMetricsObserver },
};
int register_android_view_ThreadedRenderer(JNIEnv* env) {
- jclass clazz = FindClassOrDie(env, "android/view/FrameStatsObserver");
- gFrameStatsObserverClassInfo.messageQueue =
- GetFieldIDOrDie(env, clazz, "mMessageQueue", "Landroid/os/MessageQueue;");
- gFrameStatsObserverClassInfo.buffer =
- GetFieldIDOrDie(env, clazz, "mBuffer", "[J");
- gFrameStatsObserverClassInfo.notifyData =
- GetMethodIDOrDie(env, clazz, "notifyDataAvailable", "()V");
+ jclass observerClass = FindClassOrDie(env, "android/view/FrameMetricsObserver");
+ gFrameMetricsObserverClassInfo.frameMetrics = GetFieldIDOrDie(
+ env, observerClass, "mFrameMetrics", "Landroid/view/FrameMetrics;");
+ gFrameMetricsObserverClassInfo.messageQueue = GetFieldIDOrDie(
+ env, observerClass, "mMessageQueue", "Landroid/os/MessageQueue;");
+ gFrameMetricsObserverClassInfo.callback = GetMethodIDOrDie(
+ env, observerClass, "notifyDataAvailable", "(I)V");
+
+ jclass metricsClass = FindClassOrDie(env, "android/view/FrameMetrics");
+ gFrameMetricsObserverClassInfo.timingDataBuffer = GetFieldIDOrDie(
+ env, metricsClass, "mTimingData", "[J");
return RegisterMethodsOrDie(env, kClassPathName, gMethods, NELEM(gMethods));
}
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index 1db75e6..99daab4 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -425,6 +425,8 @@
<protected-broadcast android:name="android.intent.action.DYNAMIC_SENSOR_CHANGED" />
+ <protected-broadcast android:name="android.intent.action.ACTION_RADIO_OFF" />
+
<!-- ====================================================================== -->
<!-- RUNTIME PERMISSIONS -->
<!-- ====================================================================== -->
diff --git a/core/res/res/values/attrs_manifest.xml b/core/res/res/values/attrs_manifest.xml
index 3a5336c..1496d09 100644
--- a/core/res/res/values/attrs_manifest.xml
+++ b/core/res/res/values/attrs_manifest.xml
@@ -429,8 +429,10 @@
sets. -->
<attr name="multiArch" format ="boolean" />
- <!-- Specify abiOverride for multiArch application. -->
- <attr name="abiOverride" />
+ <!-- Specify whether the 32 bit version of the ABI should be used in a
+ multiArch application. If both abioverride flag (i.e. using abi option of abd install)
+ and use32bitAbi are used, then use32bit is ignored.-->
+ <attr name="use32bitAbi" />
<!-- Specify whether a component is allowed to have multiple instances
of itself running in different processes. Use with the activity
diff --git a/core/res/res/values/public.xml b/core/res/res/values/public.xml
index 5c5aff0..69d005c 100644
--- a/core/res/res/values/public.xml
+++ b/core/res/res/values/public.xml
@@ -2696,7 +2696,7 @@
<public type="attr" name="endX" />
<public type="attr" name="endY" />
<public type="attr" name="offset" />
- <public type="attr" name="abiOverride" />
+ <public type="attr" name="use32bitAbi" />
<public type="attr" name="bitmap" />
<public type="attr" name="hotSpotX" />
<public type="attr" name="hotSpotY" />
diff --git a/core/tests/coretests/src/com/android/internal/inputmethod/InputMethodUtilsTest.java b/core/tests/coretests/src/com/android/internal/inputmethod/InputMethodUtilsTest.java
index d133a12..93581db 100644
--- a/core/tests/coretests/src/com/android/internal/inputmethod/InputMethodUtilsTest.java
+++ b/core/tests/coretests/src/com/android/internal/inputmethod/InputMethodUtilsTest.java
@@ -20,11 +20,13 @@
import android.content.pm.ApplicationInfo;
import android.content.pm.ResolveInfo;
import android.content.pm.ServiceInfo;
+import android.content.res.Configuration;
import android.os.Parcel;
import android.test.InstrumentationTestCase;
import android.test.suitebuilder.annotation.SmallTest;
import android.util.ArrayMap;
import android.util.ArraySet;
+import android.util.LocaleList;
import android.view.inputmethod.InputMethodInfo;
import android.view.inputmethod.InputMethodSubtype.InputMethodSubtypeBuilder;
import android.view.inputmethod.InputMethodSubtype;
@@ -230,7 +232,10 @@
"com.android.apps.inputmethod.latin", "DummyLatinIme", !IS_AUX, IS_DEFAULT,
subtypes);
final ArrayList<InputMethodSubtype> result =
- callGetImplicitlyApplicableSubtypesLockedWithLocale(LOCALE_EN_US, imi);
+ InputMethodUtils.getImplicitlyApplicableSubtypesLocked(
+ createTargetContextWithLocales(new LocaleList(LOCALE_EN_US))
+ .getResources(),
+ imi);
assertEquals(1, result.size());
verifyEquality(autoSubtype, result.get(0));
}
@@ -251,8 +256,10 @@
"com.android.apps.inputmethod.latin", "DummyLatinIme", !IS_AUX, IS_DEFAULT,
subtypes);
final ArrayList<InputMethodSubtype> result =
- callGetImplicitlyApplicableSubtypesLockedWithLocale(LOCALE_EN_US, imi);
- assertEquals(1, result.size());
+ InputMethodUtils.getImplicitlyApplicableSubtypesLocked(
+ createTargetContextWithLocales(new LocaleList(LOCALE_EN_US))
+ .getResources(),
+ imi);
verifyEquality(nonAutoEnUS, result.get(0));
}
@@ -271,7 +278,10 @@
"com.android.apps.inputmethod.latin", "DummyLatinIme", !IS_AUX, IS_DEFAULT,
subtypes);
final ArrayList<InputMethodSubtype> result =
- callGetImplicitlyApplicableSubtypesLockedWithLocale(LOCALE_EN_GB, imi);
+ InputMethodUtils.getImplicitlyApplicableSubtypesLocked(
+ createTargetContextWithLocales(new LocaleList(LOCALE_EN_GB))
+ .getResources(),
+ imi);
assertEquals(1, result.size());
verifyEquality(nonAutoEnGB, result.get(0));
}
@@ -292,7 +302,10 @@
"com.android.apps.inputmethod.latin", "DummyLatinIme", !IS_AUX, IS_DEFAULT,
subtypes);
final ArrayList<InputMethodSubtype> result =
- callGetImplicitlyApplicableSubtypesLockedWithLocale(LOCALE_FR, imi);
+ InputMethodUtils.getImplicitlyApplicableSubtypesLocked(
+ createTargetContextWithLocales(new LocaleList(LOCALE_FR))
+ .getResources(),
+ imi);
assertEquals(1, result.size());
verifyEquality(nonAutoFrCA, result.get(0));
}
@@ -309,7 +322,10 @@
"com.android.apps.inputmethod.latin", "DummyLatinIme", !IS_AUX, IS_DEFAULT,
subtypes);
final ArrayList<InputMethodSubtype> result =
- callGetImplicitlyApplicableSubtypesLockedWithLocale(LOCALE_FR_CA, imi);
+ InputMethodUtils.getImplicitlyApplicableSubtypesLocked(
+ createTargetContextWithLocales(new LocaleList(LOCALE_FR_CA))
+ .getResources(),
+ imi);
assertEquals(1, result.size());
verifyEquality(nonAutoFrCA, result.get(0));
}
@@ -327,7 +343,10 @@
"com.android.apps.inputmethod.latin", "DummyLatinIme", !IS_AUX, IS_DEFAULT,
subtypes);
final ArrayList<InputMethodSubtype> result =
- callGetImplicitlyApplicableSubtypesLockedWithLocale(LOCALE_JA_JP, imi);
+ InputMethodUtils.getImplicitlyApplicableSubtypesLocked(
+ createTargetContextWithLocales(new LocaleList(LOCALE_JA_JP))
+ .getResources(),
+ imi);
assertEquals(3, result.size());
verifyEquality(nonAutoJa, result.get(0));
verifyEquality(nonAutoEnabledWhenDefaultIsNotAsciiCalableSubtype, result.get(1));
@@ -344,7 +363,10 @@
"com.android.apps.inputmethod.latin", "DummyLatinIme", !IS_AUX, IS_DEFAULT,
subtypes);
final ArrayList<InputMethodSubtype> result =
- callGetImplicitlyApplicableSubtypesLockedWithLocale(LOCALE_FIL_PH, imi);
+ InputMethodUtils.getImplicitlyApplicableSubtypesLocked(
+ createTargetContextWithLocales(new LocaleList(LOCALE_FIL_PH))
+ .getResources(),
+ imi);
assertEquals(1, result.size());
verifyEquality(nonAutoFil, result.get(0));
}
@@ -361,7 +383,10 @@
"com.android.apps.inputmethod.latin", "DummyLatinIme", !IS_AUX, IS_DEFAULT,
subtypes);
final ArrayList<InputMethodSubtype> result =
- callGetImplicitlyApplicableSubtypesLockedWithLocale(LOCALE_FI, imi);
+ InputMethodUtils.getImplicitlyApplicableSubtypesLocked(
+ createTargetContextWithLocales(new LocaleList(LOCALE_FI))
+ .getResources(),
+ imi);
assertEquals(1, result.size());
verifyEquality(nonAutoJa, result.get(0));
}
@@ -376,7 +401,10 @@
"com.android.apps.inputmethod.latin", "DummyLatinIme", !IS_AUX, IS_DEFAULT,
subtypes);
final ArrayList<InputMethodSubtype> result =
- callGetImplicitlyApplicableSubtypesLockedWithLocale(LOCALE_IN, imi);
+ InputMethodUtils.getImplicitlyApplicableSubtypesLocked(
+ createTargetContextWithLocales(new LocaleList(LOCALE_IN))
+ .getResources(),
+ imi);
assertEquals(1, result.size());
verifyEquality(nonAutoIn, result.get(0));
}
@@ -389,7 +417,10 @@
"com.android.apps.inputmethod.latin", "DummyLatinIme", !IS_AUX, IS_DEFAULT,
subtypes);
final ArrayList<InputMethodSubtype> result =
- callGetImplicitlyApplicableSubtypesLockedWithLocale(LOCALE_ID, imi);
+ InputMethodUtils.getImplicitlyApplicableSubtypesLocked(
+ createTargetContextWithLocales(new LocaleList(LOCALE_ID))
+ .getResources(),
+ imi);
assertEquals(1, result.size());
verifyEquality(nonAutoIn, result.get(0));
}
@@ -402,7 +433,10 @@
"com.android.apps.inputmethod.latin", "DummyLatinIme", !IS_AUX, IS_DEFAULT,
subtypes);
final ArrayList<InputMethodSubtype> result =
- callGetImplicitlyApplicableSubtypesLockedWithLocale(LOCALE_IN, imi);
+ InputMethodUtils.getImplicitlyApplicableSubtypesLocked(
+ createTargetContextWithLocales(new LocaleList(LOCALE_IN))
+ .getResources(),
+ imi);
assertEquals(1, result.size());
verifyEquality(nonAutoId, result.get(0));
}
@@ -415,7 +449,10 @@
"com.android.apps.inputmethod.latin", "DummyLatinIme", !IS_AUX, IS_DEFAULT,
subtypes);
final ArrayList<InputMethodSubtype> result =
- callGetImplicitlyApplicableSubtypesLockedWithLocale(LOCALE_ID, imi);
+ InputMethodUtils.getImplicitlyApplicableSubtypesLocked(
+ createTargetContextWithLocales(new LocaleList(LOCALE_ID))
+ .getResources(),
+ imi);
assertEquals(1, result.size());
verifyEquality(nonAutoId, result.get(0));
}
@@ -568,24 +605,11 @@
}
}
- private ArrayList<InputMethodSubtype> callGetImplicitlyApplicableSubtypesLockedWithLocale(
- final Locale locale, final InputMethodInfo imi) {
- final Context context = getInstrumentation().getTargetContext();
- final Locale initialLocale = context.getResources().getConfiguration().locale;
- try {
- context.getResources().getConfiguration().setLocale(locale);
- return InputMethodUtils.getImplicitlyApplicableSubtypesLocked(context.getResources(),
- imi);
- } finally {
- context.getResources().getConfiguration().setLocale(initialLocale);
- }
- }
-
private void assertDefaultEnabledImes(final ArrayList<InputMethodInfo> preinstalledImes,
final Locale systemLocale, final boolean isSystemReady, String... expectedImeNames) {
- final Context context = getInstrumentation().getTargetContext();
- final String[] actualImeNames = getPackageNames(callGetDefaultEnabledImesWithLocale(
- context, isSystemReady, preinstalledImes, systemLocale));
+ final Context context = createTargetContextWithLocales(new LocaleList(systemLocale));
+ final String[] actualImeNames = getPackageNames(
+ InputMethodUtils.getDefaultEnabledImes(context, isSystemReady, preinstalledImes));
assertEquals(expectedImeNames.length, actualImeNames.length);
for (int i = 0; i < expectedImeNames.length; ++i) {
assertEquals(expectedImeNames[i], actualImeNames[i]);
@@ -606,16 +630,12 @@
}
}
- private static ArrayList<InputMethodInfo> callGetDefaultEnabledImesWithLocale(
- final Context context, final boolean isSystemReady,
- final ArrayList<InputMethodInfo> imis, final Locale locale) {
- final Locale initialLocale = context.getResources().getConfiguration().locale;
- try {
- context.getResources().getConfiguration().setLocale(locale);
- return InputMethodUtils.getDefaultEnabledImes(context, isSystemReady, imis);
- } finally {
- context.getResources().getConfiguration().setLocale(initialLocale);
- }
+ private Context createTargetContextWithLocales(final LocaleList locales) {
+ final Configuration resourceConfiguration = new Configuration();
+ resourceConfiguration.setLocales(locales);
+ return getInstrumentation()
+ .getTargetContext()
+ .createConfigurationContext(resourceConfiguration);
}
private String[] getPackageNames(final ArrayList<InputMethodInfo> imis) {
diff --git a/libs/hwui/FrameStatsObserver.h b/libs/hwui/FrameMetricsObserver.h
similarity index 86%
rename from libs/hwui/FrameStatsObserver.h
rename to libs/hwui/FrameMetricsObserver.h
index 7abc9f1..2b42a80 100644
--- a/libs/hwui/FrameStatsObserver.h
+++ b/libs/hwui/FrameMetricsObserver.h
@@ -23,9 +23,9 @@
namespace android {
namespace uirenderer {
-class FrameStatsObserver : public VirtualLightRefBase {
+class FrameMetricsObserver : public VirtualLightRefBase {
public:
- virtual void notify(BufferPool::Buffer* buffer);
+ virtual void notify(BufferPool::Buffer* buffer, int dropCount);
};
}; // namespace uirenderer
diff --git a/libs/hwui/FrameStatsReporter.h b/libs/hwui/FrameMetricsReporter.h
similarity index 83%
rename from libs/hwui/FrameStatsReporter.h
rename to libs/hwui/FrameMetricsReporter.h
index b8a9432..0831d24 100644
--- a/libs/hwui/FrameStatsReporter.h
+++ b/libs/hwui/FrameMetricsReporter.h
@@ -21,7 +21,7 @@
#include "BufferPool.h"
#include "FrameInfo.h"
-#include "FrameStatsObserver.h"
+#include "FrameMetricsObserver.h"
#include <string.h>
#include <vector>
@@ -29,18 +29,18 @@
namespace android {
namespace uirenderer {
-class FrameStatsReporter {
+class FrameMetricsReporter {
public:
- FrameStatsReporter() {
+ FrameMetricsReporter() {
mBufferPool = new BufferPool(kBufferSize, kBufferCount);
LOG_ALWAYS_FATAL_IF(mBufferPool.get() == nullptr, "OOM: unable to allocate buffer pool");
}
- void addObserver(FrameStatsObserver* observer) {
+ void addObserver(FrameMetricsObserver* observer) {
mObservers.push_back(observer);
}
- bool removeObserver(FrameStatsObserver* observer) {
+ bool removeObserver(FrameMetricsObserver* observer) {
for (size_t i = 0; i < mObservers.size(); i++) {
if (mObservers[i].get() == observer) {
mObservers.erase(mObservers.begin() + i);
@@ -54,7 +54,7 @@
return mObservers.size() > 0;
}
- void reportFrameStats(const int64_t* stats) {
+ void reportFrameMetrics(const int64_t* stats) {
BufferPool::Buffer* statsBuffer = mBufferPool->acquire();
if (statsBuffer != nullptr) {
@@ -63,11 +63,12 @@
// notify on requested threads
for (size_t i = 0; i < mObservers.size(); i++) {
- mObservers[i]->notify(statsBuffer);
+ mObservers[i]->notify(statsBuffer, mDroppedReports);
}
// drop our reference
statsBuffer->release();
+ mDroppedReports = 0;
} else {
mDroppedReports++;
}
@@ -79,7 +80,7 @@
static const size_t kBufferCount = 3;
static const size_t kBufferSize = static_cast<size_t>(FrameInfoIndex::NumIndexes);
- std::vector< sp<FrameStatsObserver> > mObservers;
+ std::vector< sp<FrameMetricsObserver> > mObservers;
sp<BufferPool> mBufferPool;
diff --git a/libs/hwui/renderthread/CanvasContext.cpp b/libs/hwui/renderthread/CanvasContext.cpp
index ea702c0..4f528b1 100644
--- a/libs/hwui/renderthread/CanvasContext.cpp
+++ b/libs/hwui/renderthread/CanvasContext.cpp
@@ -507,8 +507,8 @@
mJankTracker.addFrame(*mCurrentFrameInfo);
mRenderThread.jankTracker().addFrame(*mCurrentFrameInfo);
- if (CC_UNLIKELY(mFrameStatsReporter.get() != nullptr)) {
- mFrameStatsReporter->reportFrameStats(mCurrentFrameInfo->data());
+ if (CC_UNLIKELY(mFrameMetricsReporter.get() != nullptr)) {
+ mFrameMetricsReporter->reportFrameMetrics(mCurrentFrameInfo->data());
}
GpuMemoryTracker::onFrameCompleted();
diff --git a/libs/hwui/renderthread/CanvasContext.h b/libs/hwui/renderthread/CanvasContext.h
index 168166e..1f81970 100644
--- a/libs/hwui/renderthread/CanvasContext.h
+++ b/libs/hwui/renderthread/CanvasContext.h
@@ -20,7 +20,7 @@
#include "DamageAccumulator.h"
#include "FrameInfo.h"
#include "FrameInfoVisualizer.h"
-#include "FrameStatsReporter.h"
+#include "FrameMetricsReporter.h"
#include "IContextFactory.h"
#include "LayerUpdateQueue.h"
#include "RenderNode.h"
@@ -142,26 +142,26 @@
return mRenderThread.renderState();
}
- void addFrameStatsObserver(FrameStatsObserver* observer) {
- if (mFrameStatsReporter.get() == nullptr) {
- mFrameStatsReporter.reset(new FrameStatsReporter());
+ void addFrameMetricsObserver(FrameMetricsObserver* observer) {
+ if (mFrameMetricsReporter.get() == nullptr) {
+ mFrameMetricsReporter.reset(new FrameMetricsReporter());
}
- mFrameStatsReporter->addObserver(observer);
+ mFrameMetricsReporter->addObserver(observer);
}
- void removeFrameStatsObserver(FrameStatsObserver* observer) {
- if (mFrameStatsReporter.get() != nullptr) {
- mFrameStatsReporter->removeObserver(observer);
- if (!mFrameStatsReporter->hasObservers()) {
- mFrameStatsReporter.reset(nullptr);
+ void removeFrameMetricsObserver(FrameMetricsObserver* observer) {
+ if (mFrameMetricsReporter.get() != nullptr) {
+ mFrameMetricsReporter->removeObserver(observer);
+ if (!mFrameMetricsReporter->hasObservers()) {
+ mFrameMetricsReporter.reset(nullptr);
}
}
}
long getDroppedFrameReportCount() {
- if (mFrameStatsReporter.get() != nullptr) {
- return mFrameStatsReporter->getDroppedReports();
+ if (mFrameMetricsReporter.get() != nullptr) {
+ return mFrameMetricsReporter->getDroppedReports();
}
return 0;
@@ -215,7 +215,7 @@
std::string mName;
JankTracker mJankTracker;
FrameInfoVisualizer mProfiler;
- std::unique_ptr<FrameStatsReporter> mFrameStatsReporter;
+ std::unique_ptr<FrameMetricsReporter> mFrameMetricsReporter;
std::set<RenderNode*> mPrefetechedLayers;
diff --git a/libs/hwui/renderthread/RenderProxy.cpp b/libs/hwui/renderthread/RenderProxy.cpp
index 7c6cd7e..04223a7 100644
--- a/libs/hwui/renderthread/RenderProxy.cpp
+++ b/libs/hwui/renderthread/RenderProxy.cpp
@@ -568,17 +568,17 @@
post(task);
}
-CREATE_BRIDGE2(addFrameStatsObserver, CanvasContext* context,
- FrameStatsObserver* frameStatsObserver) {
- args->context->addFrameStatsObserver(args->frameStatsObserver);
+CREATE_BRIDGE2(addFrameMetricsObserver, CanvasContext* context,
+ FrameMetricsObserver* frameStatsObserver) {
+ args->context->addFrameMetricsObserver(args->frameStatsObserver);
if (args->frameStatsObserver != nullptr) {
args->frameStatsObserver->decStrong(args->context);
}
return nullptr;
}
-void RenderProxy::addFrameStatsObserver(FrameStatsObserver* observer) {
- SETUP_TASK(addFrameStatsObserver);
+void RenderProxy::addFrameMetricsObserver(FrameMetricsObserver* observer) {
+ SETUP_TASK(addFrameMetricsObserver);
args->context = mContext;
args->frameStatsObserver = observer;
if (observer != nullptr) {
@@ -587,17 +587,17 @@
post(task);
}
-CREATE_BRIDGE2(removeFrameStatsObserver, CanvasContext* context,
- FrameStatsObserver* frameStatsObserver) {
- args->context->removeFrameStatsObserver(args->frameStatsObserver);
+CREATE_BRIDGE2(removeFrameMetricsObserver, CanvasContext* context,
+ FrameMetricsObserver* frameStatsObserver) {
+ args->context->removeFrameMetricsObserver(args->frameStatsObserver);
if (args->frameStatsObserver != nullptr) {
args->frameStatsObserver->decStrong(args->context);
}
return nullptr;
}
-void RenderProxy::removeFrameStatsObserver(FrameStatsObserver* observer) {
- SETUP_TASK(removeFrameStatsObserver);
+void RenderProxy::removeFrameMetricsObserver(FrameMetricsObserver* observer) {
+ SETUP_TASK(removeFrameMetricsObserver);
args->context = mContext;
args->frameStatsObserver = observer;
if (observer != nullptr) {
@@ -606,16 +606,6 @@
post(task);
}
-CREATE_BRIDGE1(getDroppedFrameReportCount, CanvasContext* context) {
- return (void*) args->context->getDroppedFrameReportCount();
-}
-
-long RenderProxy::getDroppedFrameReportCount() {
- SETUP_TASK(getDroppedFrameReportCount);
- args->context = mContext;
- return (long) postAndWait(task);
-}
-
void RenderProxy::post(RenderTask* task) {
mRenderThread.queue(task);
}
diff --git a/libs/hwui/renderthread/RenderProxy.h b/libs/hwui/renderthread/RenderProxy.h
index 178724a..8d65a82 100644
--- a/libs/hwui/renderthread/RenderProxy.h
+++ b/libs/hwui/renderthread/RenderProxy.h
@@ -29,7 +29,7 @@
#include <utils/StrongPointer.h>
#include "../Caches.h"
-#include "../FrameStatsObserver.h"
+#include "../FrameMetricsObserver.h"
#include "../IContextFactory.h"
#include "CanvasContext.h"
#include "DrawFrameTask.h"
@@ -113,8 +113,8 @@
ANDROID_API void drawRenderNode(RenderNode* node);
ANDROID_API void setContentDrawBounds(int left, int top, int right, int bottom);
- ANDROID_API void addFrameStatsObserver(FrameStatsObserver* observer);
- ANDROID_API void removeFrameStatsObserver(FrameStatsObserver* observer);
+ ANDROID_API void addFrameMetricsObserver(FrameMetricsObserver* observer);
+ ANDROID_API void removeFrameMetricsObserver(FrameMetricsObserver* observer);
ANDROID_API long getDroppedFrameReportCount();
private:
diff --git a/media/java/android/media/AudioRecord.java b/media/java/android/media/AudioRecord.java
index 800b914..e342385 100644
--- a/media/java/android/media/AudioRecord.java
+++ b/media/java/android/media/AudioRecord.java
@@ -1014,9 +1014,12 @@
* Reads audio data from the audio hardware for recording into a byte array.
* The format specified in the AudioRecord constructor should be
* {@link AudioFormat#ENCODING_PCM_8BIT} to correspond to the data in the array.
+ * The format can be {@link AudioFormat#ENCODING_PCM_16BIT}, but this is deprecated.
* @param audioData the array to which the recorded audio data is written.
- * @param offsetInBytes index in audioData from which the data is written expressed in bytes.
+ * @param offsetInBytes index in audioData to which the data is written expressed in bytes.
+ * Must not be negative, or cause the data access to go out of bounds of the array.
* @param sizeInBytes the number of requested bytes.
+ * Must not be negative, or cause the data access to go out of bounds of the array.
* @param readMode one of {@link #READ_BLOCKING}, {@link #READ_NON_BLOCKING}.
* <br>With {@link #READ_BLOCKING}, the read will block until all the requested data
* is read.
@@ -1025,7 +1028,8 @@
* @return the number of bytes that were read or {@link #ERROR_INVALID_OPERATION}
* if the object wasn't properly initialized, or {@link #ERROR_BAD_VALUE} if
* the parameters don't resolve to valid data and indexes.
- * The number of bytes will not exceed sizeInBytes.
+ * The number of bytes will be a multiple of the frame size in bytes
+ * not to exceed sizeInBytes.
*/
public int read(@NonNull byte[] audioData, int offsetInBytes, int sizeInBytes,
@ReadMode int readMode) {
@@ -1053,12 +1057,14 @@
* The format specified in the AudioRecord constructor should be
* {@link AudioFormat#ENCODING_PCM_16BIT} to correspond to the data in the array.
* @param audioData the array to which the recorded audio data is written.
- * @param offsetInShorts index in audioData from which the data is written expressed in shorts.
+ * @param offsetInShorts index in audioData to which the data is written expressed in shorts.
+ * Must not be negative, or cause the data access to go out of bounds of the array.
* @param sizeInShorts the number of requested shorts.
+ * Must not be negative, or cause the data access to go out of bounds of the array.
* @return the number of shorts that were read or {@link #ERROR_INVALID_OPERATION}
* if the object wasn't properly initialized, or {@link #ERROR_BAD_VALUE} if
* the parameters don't resolve to valid data and indexes.
- * The number of shorts will not exceed sizeInShorts.
+ * The number of shorts will be a multiple of the channel count not to exceed sizeInShorts.
*/
public int read(@NonNull short[] audioData, int offsetInShorts, int sizeInShorts) {
return read(audioData, offsetInShorts, sizeInShorts, READ_BLOCKING);
@@ -1070,7 +1076,9 @@
* {@link AudioFormat#ENCODING_PCM_16BIT} to correspond to the data in the array.
* @param audioData the array to which the recorded audio data is written.
* @param offsetInShorts index in audioData from which the data is written expressed in shorts.
+ * Must not be negative, or cause the data access to go out of bounds of the array.
* @param sizeInShorts the number of requested shorts.
+ * Must not be negative, or cause the data access to go out of bounds of the array.
* @param readMode one of {@link #READ_BLOCKING}, {@link #READ_NON_BLOCKING}.
* <br>With {@link #READ_BLOCKING}, the read will block until all the requested data
* is read.
@@ -1079,7 +1087,7 @@
* @return the number of shorts that were read or {@link #ERROR_INVALID_OPERATION}
* if the object wasn't properly initialized, or {@link #ERROR_BAD_VALUE} if
* the parameters don't resolve to valid data and indexes.
- * The number of shorts will not exceed sizeInShorts.
+ * The number of shorts will be a multiple of the channel count not to exceed sizeInShorts.
*/
public int read(@NonNull short[] audioData, int offsetInShorts, int sizeInShorts,
@ReadMode int readMode) {
@@ -1108,7 +1116,9 @@
* {@link AudioFormat#ENCODING_PCM_FLOAT} to correspond to the data in the array.
* @param audioData the array to which the recorded audio data is written.
* @param offsetInFloats index in audioData from which the data is written.
+ * Must not be negative, or cause the data access to go out of bounds of the array.
* @param sizeInFloats the number of requested floats.
+ * Must not be negative, or cause the data access to go out of bounds of the array.
* @param readMode one of {@link #READ_BLOCKING}, {@link #READ_NON_BLOCKING}.
* <br>With {@link #READ_BLOCKING}, the read will block until all the requested data
* is read.
@@ -1117,7 +1127,7 @@
* @return the number of floats that were read or {@link #ERROR_INVALID_OPERATION}
* if the object wasn't properly initialized, or {@link #ERROR_BAD_VALUE} if
* the parameters don't resolve to valid data and indexes.
- * The number of floats will not exceed sizeInFloats.
+ * The number of floats will be a multiple of the channel count not to exceed sizeInFloats.
*/
public int read(@NonNull float[] audioData, int offsetInFloats, int sizeInFloats,
@ReadMode int readMode) {
@@ -1154,6 +1164,7 @@
* The representation of the data in the buffer will depend on the format specified in
* the AudioRecord constructor, and will be native endian.
* @param audioBuffer the direct buffer to which the recorded audio data is written.
+ * Data is written to audioBuffer.position().
* @param sizeInBytes the number of requested bytes. It is recommended but not enforced
* that the number of bytes requested be a multiple of the frame size (sample size in
* bytes multiplied by the channel count).
@@ -1161,7 +1172,7 @@
* if the object wasn't properly initialized, or {@link #ERROR_BAD_VALUE} if
* the parameters don't resolve to valid data and indexes.
* The number of bytes will not exceed sizeInBytes.
- * The number of bytes read will truncated to be a multiple of the frame size.
+ * The number of bytes read will be truncated to be a multiple of the frame size.
*/
public int read(@NonNull ByteBuffer audioBuffer, int sizeInBytes) {
return read(audioBuffer, sizeInBytes, READ_BLOCKING);
@@ -1175,6 +1186,7 @@
* The representation of the data in the buffer will depend on the format specified in
* the AudioRecord constructor, and will be native endian.
* @param audioBuffer the direct buffer to which the recorded audio data is written.
+ * Data is written to audioBuffer.position().
* @param sizeInBytes the number of requested bytes. It is recommended but not enforced
* that the number of bytes requested be a multiple of the frame size (sample size in
* bytes multiplied by the channel count).
@@ -1187,7 +1199,7 @@
* if the object wasn't properly initialized, or {@link #ERROR_BAD_VALUE} if
* the parameters don't resolve to valid data and indexes.
* The number of bytes will not exceed sizeInBytes.
- * The number of bytes read will truncated to be a multiple of the frame size.
+ * The number of bytes read will be truncated to be a multiple of the frame size.
*/
public int read(@NonNull ByteBuffer audioBuffer, int sizeInBytes, @ReadMode int readMode) {
if (mState != STATE_INITIALIZED) {
diff --git a/media/java/android/media/AudioTrack.java b/media/java/android/media/AudioTrack.java
index b26b310..bdf6d9f 100644
--- a/media/java/android/media/AudioTrack.java
+++ b/media/java/android/media/AudioTrack.java
@@ -1774,6 +1774,7 @@
* or copies audio data for later playback (static buffer mode).
* The format specified in the AudioTrack constructor should be
* {@link AudioFormat#ENCODING_PCM_8BIT} to correspond to the data in the array.
+ * The format can be {@link AudioFormat#ENCODING_PCM_16BIT}, but this is deprecated.
* <p>
* In streaming mode, the write will normally block until all the data has been enqueued for
* playback, and will return a full transfer count. However, if the track is stopped or paused
@@ -1786,7 +1787,9 @@
* @param audioData the array that holds the data to play.
* @param offsetInBytes the offset expressed in bytes in audioData where the data to write
* starts.
+ * Must not be negative, or cause the data access to go out of bounds of the array.
* @param sizeInBytes the number of bytes to write in audioData after the offset.
+ * Must not be negative, or cause the data access to go out of bounds of the array.
* @return zero or the positive number of bytes that were written, or
* {@link #ERROR_INVALID_OPERATION}
* if the track isn't properly initialized, or {@link #ERROR_BAD_VALUE} if
@@ -1795,6 +1798,8 @@
* needs to be recreated.
* The dead object error code is not returned if some data was successfully transferred.
* In this case, the error is returned at the next write().
+ * The number of bytes will be a multiple of the frame size in bytes
+ * not to exceed sizeInBytes.
*
* This is equivalent to {@link #write(byte[], int, int, int)} with <code>writeMode</code>
* set to {@link #WRITE_BLOCKING}.
@@ -1808,6 +1813,7 @@
* or copies audio data for later playback (static buffer mode).
* The format specified in the AudioTrack constructor should be
* {@link AudioFormat#ENCODING_PCM_8BIT} to correspond to the data in the array.
+ * The format can be {@link AudioFormat#ENCODING_PCM_16BIT}, but this is deprecated.
* <p>
* In streaming mode, the blocking behavior depends on the write mode. If the write mode is
* {@link #WRITE_BLOCKING}, the write will normally block until all the data has been enqueued
@@ -1823,7 +1829,9 @@
* @param audioData the array that holds the data to play.
* @param offsetInBytes the offset expressed in bytes in audioData where the data to write
* starts.
+ * Must not be negative, or cause the data access to go out of bounds of the array.
* @param sizeInBytes the number of bytes to write in audioData after the offset.
+ * Must not be negative, or cause the data access to go out of bounds of the array.
* @param writeMode one of {@link #WRITE_BLOCKING}, {@link #WRITE_NON_BLOCKING}. It has no
* effect in static mode.
* <br>With {@link #WRITE_BLOCKING}, the write will block until all data has been written
@@ -1838,6 +1846,8 @@
* needs to be recreated.
* The dead object error code is not returned if some data was successfully transferred.
* In this case, the error is returned at the next write().
+ * The number of bytes will be a multiple of the frame size in bytes
+ * not to exceed sizeInBytes.
*/
public int write(@NonNull byte[] audioData, int offsetInBytes, int sizeInBytes,
@WriteMode int writeMode) {
@@ -1887,7 +1897,9 @@
* @param audioData the array that holds the data to play.
* @param offsetInShorts the offset expressed in shorts in audioData where the data to play
* starts.
+ * Must not be negative, or cause the data access to go out of bounds of the array.
* @param sizeInShorts the number of shorts to read in audioData after the offset.
+ * Must not be negative, or cause the data access to go out of bounds of the array.
* @return zero or the positive number of shorts that were written, or
* {@link #ERROR_INVALID_OPERATION}
* if the track isn't properly initialized, or {@link #ERROR_BAD_VALUE} if
@@ -1896,6 +1908,7 @@
* needs to be recreated.
* The dead object error code is not returned if some data was successfully transferred.
* In this case, the error is returned at the next write().
+ * The number of shorts will be a multiple of the channel count not to exceed sizeInShorts.
*
* This is equivalent to {@link #write(short[], int, int, int)} with <code>writeMode</code>
* set to {@link #WRITE_BLOCKING}.
@@ -1923,7 +1936,9 @@
* @param audioData the array that holds the data to write.
* @param offsetInShorts the offset expressed in shorts in audioData where the data to write
* starts.
+ * Must not be negative, or cause the data access to go out of bounds of the array.
* @param sizeInShorts the number of shorts to read in audioData after the offset.
+ * Must not be negative, or cause the data access to go out of bounds of the array.
* @param writeMode one of {@link #WRITE_BLOCKING}, {@link #WRITE_NON_BLOCKING}. It has no
* effect in static mode.
* <br>With {@link #WRITE_BLOCKING}, the write will block until all data has been written
@@ -1938,6 +1953,7 @@
* needs to be recreated.
* The dead object error code is not returned if some data was successfully transferred.
* In this case, the error is returned at the next write().
+ * The number of shorts will be a multiple of the channel count not to exceed sizeInShorts.
*/
public int write(@NonNull short[] audioData, int offsetInShorts, int sizeInShorts,
@WriteMode int writeMode) {
@@ -1999,7 +2015,9 @@
* to provide samples values within the nominal range.
* @param offsetInFloats the offset, expressed as a number of floats,
* in audioData where the data to write starts.
+ * Must not be negative, or cause the data access to go out of bounds of the array.
* @param sizeInFloats the number of floats to write in audioData after the offset.
+ * Must not be negative, or cause the data access to go out of bounds of the array.
* @param writeMode one of {@link #WRITE_BLOCKING}, {@link #WRITE_NON_BLOCKING}. It has no
* effect in static mode.
* <br>With {@link #WRITE_BLOCKING}, the write will block until all data has been written
@@ -2014,6 +2032,7 @@
* needs to be recreated.
* The dead object error code is not returned if some data was successfully transferred.
* In this case, the error is returned at the next write().
+ * The number of floats will be a multiple of the channel count not to exceed sizeInFloats.
*/
public int write(@NonNull float[] audioData, int offsetInFloats, int sizeInFloats,
@WriteMode int writeMode) {
@@ -2075,7 +2094,9 @@
* <BR>Note that upon return, the buffer position (<code>audioData.position()</code>) will
* have been advanced to reflect the amount of data that was successfully written to
* the AudioTrack.
- * @param sizeInBytes number of bytes to write.
+ * @param sizeInBytes number of bytes to write. It is recommended but not enforced
+ * that the number of bytes requested be a multiple of the frame size (sample size in
+ * bytes multiplied by the channel count).
* <BR>Note this may differ from <code>audioData.remaining()</code>, but cannot exceed it.
* @param writeMode one of {@link #WRITE_BLOCKING}, {@link #WRITE_NON_BLOCKING}. It has no
* effect in static mode.
@@ -2142,7 +2163,9 @@
* <BR>Note that upon return, the buffer position (<code>audioData.position()</code>) will
* have been advanced to reflect the amount of data that was successfully written to
* the AudioTrack.
- * @param sizeInBytes number of bytes to write.
+ * @param sizeInBytes number of bytes to write. It is recommended but not enforced
+ * that the number of bytes requested be a multiple of the frame size (sample size in
+ * bytes multiplied by the channel count).
* <BR>Note this may differ from <code>audioData.remaining()</code>, but cannot exceed it.
* @param writeMode one of {@link #WRITE_BLOCKING}, {@link #WRITE_NON_BLOCKING}.
* <BR>With {@link #WRITE_BLOCKING}, the write will block until all data has been written
diff --git a/packages/MtpDocumentsProvider/src/com/android/mtp/Mapper.java b/packages/MtpDocumentsProvider/src/com/android/mtp/Mapper.java
index 3faa8f4..6af492c 100644
--- a/packages/MtpDocumentsProvider/src/com/android/mtp/Mapper.java
+++ b/packages/MtpDocumentsProvider/src/com/android/mtp/Mapper.java
@@ -73,7 +73,6 @@
extraValuesList,
COLUMN_PARENT_DOCUMENT_ID + " IS NULL",
EMPTY_ARGS,
- /* heuristic */ false,
COLUMN_DEVICE_ID);
database.setTransactionSuccessful();
return changed;
@@ -92,16 +91,13 @@
final SQLiteDatabase database = mDatabase.getSQLiteDatabase();
database.beginTransaction();
try {
- final boolean heuristic;
final String mapColumn;
Preconditions.checkState(mMappingMode.containsKey(parentDocumentId));
switch (mMappingMode.get(parentDocumentId)) {
case MAP_BY_MTP_IDENTIFIER:
- heuristic = false;
mapColumn = COLUMN_STORAGE_ID;
break;
case MAP_BY_NAME:
- heuristic = true;
mapColumn = Document.COLUMN_DISPLAY_NAME;
break;
default:
@@ -120,7 +116,6 @@
extraValuesList,
COLUMN_PARENT_DOCUMENT_ID + "=?",
strings(parentDocumentId),
- heuristic,
mapColumn);
database.setTransactionSuccessful();
@@ -137,16 +132,13 @@
* @param documents List of document information.
*/
synchronized void putChildDocuments(int deviceId, String parentId, MtpObjectInfo[] documents) {
- final boolean heuristic;
final String mapColumn;
Preconditions.checkState(mMappingMode.containsKey(parentId));
switch (mMappingMode.get(parentId)) {
case MAP_BY_MTP_IDENTIFIER:
- heuristic = false;
mapColumn = COLUMN_OBJECT_HANDLE;
break;
case MAP_BY_NAME:
- heuristic = true;
mapColumn = Document.COLUMN_DISPLAY_NAME;
break;
default:
@@ -163,17 +155,13 @@
null,
COLUMN_PARENT_DOCUMENT_ID + "=?",
strings(parentId),
- heuristic,
mapColumn);
}
- @VisibleForTesting
void clearMapping() {
final SQLiteDatabase database = mDatabase.getSQLiteDatabase();
database.beginTransaction();
try {
- mDatabase.deleteDocumentsAndRootsRecursively(
- COLUMN_ROW_STATE + " = ?", strings(ROW_STATE_PENDING));
final ContentValues values = new ContentValues();
values.putNull(COLUMN_OBJECT_HANDLE);
values.putNull(COLUMN_STORAGE_ID);
@@ -209,11 +197,6 @@
final SQLiteDatabase database = mDatabase.getSQLiteDatabase();
database.beginTransaction();
try {
- // Delete all pending rows.
- mDatabase.deleteDocumentsAndRootsRecursively(
- selection + " AND " + COLUMN_ROW_STATE + "=?",
- DatabaseUtils.appendSelectionArgs(args, strings(ROW_STATE_PENDING)));
-
// Set all documents as invalidated.
final ContentValues values = new ContentValues();
values.put(COLUMN_ROW_STATE, ROW_STATE_INVALIDATED);
@@ -245,7 +228,6 @@
* @param rootExtraValuesList Values for root extra to be stored in the database.
* @param selection SQL where closure to select rows that shares the same parent.
* @param args Argument for selection SQL.
- * @param heuristic Whether the mapping mode is heuristic.
* @return Whether the method adds new rows.
*/
private boolean putDocuments(
@@ -253,7 +235,6 @@
@Nullable ContentValues[] rootExtraValuesList,
String selection,
String[] args,
- boolean heuristic,
String mappingKey) {
final SQLiteDatabase database = mDatabase.getSQLiteDatabase();
boolean added = false;
@@ -285,7 +266,7 @@
if (candidateCursor.getCount() == 0) {
rowId = database.insert(TABLE_DOCUMENTS, null, values);
added = true;
- } else if (!heuristic) {
+ } else {
candidateCursor.moveToNext();
rowId = candidateCursor.getLong(0);
database.update(
@@ -293,9 +274,6 @@
values,
SELECTION_DOCUMENT_ID,
strings(rowId));
- } else {
- values.put(COLUMN_ROW_STATE, ROW_STATE_PENDING);
- rowId = database.insertOrThrow(TABLE_DOCUMENTS, null, values);
}
// Document ID is a primary integer key of the table. So the returned row
// IDs should be same with the document ID.
@@ -334,84 +312,10 @@
selection = COLUMN_PARENT_DOCUMENT_ID + " IS NULL";
args = EMPTY_ARGS;
}
- final String groupKey;
- switch (mMappingMode.get(parentId)) {
- case MAP_BY_MTP_IDENTIFIER:
- groupKey = parentId != null ? COLUMN_OBJECT_HANDLE : COLUMN_STORAGE_ID;
- break;
- case MAP_BY_NAME:
- groupKey = Document.COLUMN_DISPLAY_NAME;
- break;
- default:
- throw new Error("Unexpected mapping state.");
- }
mMappingMode.remove(parentId);
final SQLiteDatabase database = mDatabase.getSQLiteDatabase();
database.beginTransaction();
try {
- // Get 1-to-1 mapping of invalidated document and pending document.
- final String invalidatedIdQuery = createStateFilter(
- ROW_STATE_INVALIDATED, Document.COLUMN_DOCUMENT_ID);
- final String pendingIdQuery = createStateFilter(
- ROW_STATE_PENDING, Document.COLUMN_DOCUMENT_ID);
- // SQL should be like:
- // SELECT group_concat(CASE WHEN raw_state = 1 THEN document_id ELSE NULL END),
- // group_concat(CASE WHEN raw_state = 2 THEN document_id ELSE NULL END)
- // WHERE device_id = ? AND parent_document_id IS NULL
- // GROUP BY display_name
- // HAVING count(CASE WHEN raw_state = 1 THEN document_id ELSE NULL END) = 1 AND
- // count(CASE WHEN raw_state = 2 THEN document_id ELSE NULL END) = 1
- final Cursor mergingCursor = database.query(
- TABLE_DOCUMENTS,
- new String[] {
- "group_concat(" + invalidatedIdQuery + ")",
- "group_concat(" + pendingIdQuery + ")"
- },
- selection,
- args,
- groupKey,
- "count(" + invalidatedIdQuery + ") = 1 AND count(" + pendingIdQuery + ") = 1",
- null);
-
- final ContentValues values = new ContentValues();
- while (mergingCursor.moveToNext()) {
- final String invalidatedId = mergingCursor.getString(0);
- final String pendingId = mergingCursor.getString(1);
-
- // Obtain the new values including the latest object handle from mapping row.
- getFirstRow(
- TABLE_DOCUMENTS,
- SELECTION_DOCUMENT_ID,
- new String[] { pendingId },
- values);
- values.remove(Document.COLUMN_DOCUMENT_ID);
- values.put(COLUMN_ROW_STATE, ROW_STATE_VALID);
- database.update(
- TABLE_DOCUMENTS,
- values,
- SELECTION_DOCUMENT_ID,
- new String[] { invalidatedId });
-
- getFirstRow(
- TABLE_ROOT_EXTRA,
- SELECTION_ROOT_ID,
- new String[] { pendingId },
- values);
- if (values.size() > 0) {
- values.remove(Root.COLUMN_ROOT_ID);
- database.update(
- TABLE_ROOT_EXTRA,
- values,
- SELECTION_ROOT_ID,
- new String[] { invalidatedId });
- }
-
- // Delete 'pending' row.
- mDatabase.deleteDocumentsAndRootsRecursively(
- SELECTION_DOCUMENT_ID, new String[] { pendingId });
- }
- mergingCursor.close();
-
boolean changed = false;
// Delete all invalidated rows that cannot be mapped.
@@ -421,58 +325,10 @@
changed = true;
}
- // The database cannot find old document ID for the pending rows.
- // Turn the all pending rows into valid state, which means the rows become to be
- // valid with new document ID.
- values.clear();
- values.put(COLUMN_ROW_STATE, ROW_STATE_VALID);
- if (database.update(
- TABLE_DOCUMENTS,
- values,
- COLUMN_ROW_STATE + " = ? AND " + selection,
- DatabaseUtils.appendSelectionArgs(strings(ROW_STATE_PENDING), args)) != 0) {
- changed = true;
- }
database.setTransactionSuccessful();
return changed;
} finally {
database.endTransaction();
}
}
-
- /**
- * Obtains values of the first row for the query.
- * @param values ContentValues that the values are stored to.
- * @param table Target table.
- * @param selection Query to select rows.
- * @param args Argument for query.
- */
- private void getFirstRow(String table, String selection, String[] args, ContentValues values) {
- final SQLiteDatabase database = mDatabase.getSQLiteDatabase();
- values.clear();
- final Cursor cursor = database.query(table, null, selection, args, null, null, null, "1");
- try {
- if (cursor.getCount() == 0) {
- return;
- }
- cursor.moveToNext();
- DatabaseUtils.cursorRowToContentValues(cursor, values);
- } finally {
- cursor.close();
- }
- }
-
- /**
- * Gets SQL expression that represents the given value or NULL depends on the row state.
- * You must pass static constants to this methods otherwise you may be suffered from SQL
- * injections.
- * @param state Expected row state.
- * @param a SQL value.
- * @return Expression that represents a if the row state is expected one, and represents NULL
- * otherwise.
- */
- private static String createStateFilter(int state, String a) {
- return "CASE WHEN " + COLUMN_ROW_STATE + " = " + Integer.toString(state) +
- " THEN " + a + " ELSE NULL END";
- }
}
diff --git a/packages/MtpDocumentsProvider/src/com/android/mtp/MtpDatabaseConstants.java b/packages/MtpDocumentsProvider/src/com/android/mtp/MtpDatabaseConstants.java
index 3cfb82f..33687cb 100644
--- a/packages/MtpDocumentsProvider/src/com/android/mtp/MtpDatabaseConstants.java
+++ b/packages/MtpDocumentsProvider/src/com/android/mtp/MtpDatabaseConstants.java
@@ -78,14 +78,6 @@
static final int ROW_STATE_INVALIDATED = 1;
/**
- * The state represents the raw has a valid object handle but it may be going to be mapped with
- * another rows invalidated. After fetching all documents under the parent, the database tries
- * to map the pending documents and the invalidated documents in order to keep old document ID
- * alive.
- */
- static final int ROW_STATE_PENDING = 2;
-
- /**
* Mapping mode that uses MTP identifier to find corresponding rows.
*/
static final int MAP_BY_MTP_IDENTIFIER = 0;
diff --git a/packages/MtpDocumentsProvider/tests/src/com/android/mtp/MtpDatabaseTest.java b/packages/MtpDocumentsProvider/tests/src/com/android/mtp/MtpDatabaseTest.java
index a49dc67..a75012e 100644
--- a/packages/MtpDocumentsProvider/tests/src/com/android/mtp/MtpDatabaseTest.java
+++ b/packages/MtpDocumentsProvider/tests/src/com/android/mtp/MtpDatabaseTest.java
@@ -310,14 +310,14 @@
assertEquals(3, cursor.getCount());
cursor.moveToNext();
assertEquals(1, getInt(cursor, COLUMN_DOCUMENT_ID));
- assertTrue(isNull(cursor, COLUMN_STORAGE_ID));
+ assertEquals(200, getInt(cursor, COLUMN_STORAGE_ID));
assertEquals("Storage A", getString(cursor, COLUMN_DISPLAY_NAME));
cursor.moveToNext();
assertEquals(2, getInt(cursor, COLUMN_DOCUMENT_ID));
assertTrue(isNull(cursor, COLUMN_STORAGE_ID));
assertEquals("Storage B", getString(cursor, COLUMN_DISPLAY_NAME));
cursor.moveToNext();
- assertEquals(4, getInt(cursor, COLUMN_DOCUMENT_ID));
+ assertEquals(3, getInt(cursor, COLUMN_DOCUMENT_ID));
assertEquals(202, getInt(cursor, COLUMN_STORAGE_ID));
assertEquals("Storage C", getString(cursor, COLUMN_DISPLAY_NAME));
cursor.close();
@@ -333,7 +333,7 @@
assertEquals(200, getInt(cursor, COLUMN_STORAGE_ID));
assertEquals("Storage A", getString(cursor, COLUMN_DISPLAY_NAME));
cursor.moveToNext();
- assertEquals(4, getInt(cursor, COLUMN_DOCUMENT_ID));
+ assertEquals(3, getInt(cursor, COLUMN_DOCUMENT_ID));
assertEquals(202, getInt(cursor, COLUMN_STORAGE_ID));
assertEquals("Storage C", getString(cursor, COLUMN_DISPLAY_NAME));
cursor.close();
@@ -387,7 +387,7 @@
assertEquals(4, cursor.getCount());
cursor.moveToPosition(3);
- assertEquals(5, getInt(cursor, COLUMN_DOCUMENT_ID));
+ assertEquals(4, getInt(cursor, COLUMN_DOCUMENT_ID));
assertEquals(203, getInt(cursor, COLUMN_OBJECT_HANDLE));
assertEquals("video.mp4", getString(cursor, COLUMN_DISPLAY_NAME));
@@ -406,7 +406,7 @@
assertEquals("note.txt", getString(cursor, COLUMN_DISPLAY_NAME));
cursor.moveToNext();
- assertEquals(5, getInt(cursor, COLUMN_DOCUMENT_ID));
+ assertEquals(4, getInt(cursor, COLUMN_DOCUMENT_ID));
assertEquals(203, getInt(cursor, COLUMN_OBJECT_HANDLE));
assertEquals("video.mp4", getString(cursor, COLUMN_DISPLAY_NAME));
cursor.close();
@@ -544,7 +544,7 @@
assertEquals(1, cursor.getCount());
cursor.moveToNext();
assertEquals(2, getInt(cursor, COLUMN_DOCUMENT_ID));
- assertTrue(isNull(cursor, COLUMN_OBJECT_HANDLE));
+ assertEquals(201, getInt(cursor, COLUMN_OBJECT_HANDLE));
cursor.close();
}
}
@@ -626,11 +626,12 @@
final Cursor cursor = mDatabase.queryRootDocuments(columns);
assertEquals(2, cursor.getCount());
cursor.moveToNext();
- assertEquals(2, getInt(cursor, COLUMN_DOCUMENT_ID));
+ // One reuses exisitng document ID 1.
+ assertEquals(1, getInt(cursor, COLUMN_DOCUMENT_ID));
assertEquals(200, getInt(cursor, COLUMN_STORAGE_ID));
assertEquals("Storage", getString(cursor, COLUMN_DISPLAY_NAME));
cursor.moveToNext();
- assertEquals(3, getInt(cursor, COLUMN_DOCUMENT_ID));
+ assertEquals(2, getInt(cursor, COLUMN_DOCUMENT_ID));
assertEquals(201, getInt(cursor, COLUMN_STORAGE_ID));
assertEquals("Storage", getString(cursor, COLUMN_DISPLAY_NAME));
cursor.close();
diff --git a/packages/SystemUI/res/values/dimens.xml b/packages/SystemUI/res/values/dimens.xml
index e5e5710..6702cef 100644
--- a/packages/SystemUI/res/values/dimens.xml
+++ b/packages/SystemUI/res/values/dimens.xml
@@ -282,9 +282,6 @@
<!-- The padding between freeform workspace tasks -->
<dimen name="recents_freeform_workspace_task_padding">8dp</dimen>
- <!-- Space reserved for the cards behind the top card in the top stack -->
- <dimen name="top_stack_peek_amount">12dp</dimen>
-
<!-- Space reserved for the cards behind the top card in the bottom stack -->
<dimen name="bottom_stack_peek_amount">12dp</dimen>
@@ -295,9 +292,6 @@
<!-- The height of the area before the bottom stack in which the notifications slow down -->
<dimen name="bottom_stack_slow_down_length">12dp</dimen>
- <!-- The height of the area before the top stack in which the notifications slow down -->
- <dimen name="top_stack_slow_down_length">12dp</dimen>
-
<!-- Z distance between notifications if they are in the stack -->
<dimen name="z_distance_between_notifications">0.5dp</dimen>
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java b/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java
index 7f1316f..84b2031 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java
@@ -947,6 +947,10 @@
}
}
+ public boolean mustStayOnScreen() {
+ return mIsHeadsUp;
+ }
+
private void updateClearability() {
// public versions cannot be dismissed
mVetoButton.setVisibility(isClearable() && !mShowingPublic ? View.VISIBLE : View.GONE);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableView.java b/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableView.java
index a0fb34a..8042b60 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableView.java
@@ -399,6 +399,10 @@
return false;
}
+ public boolean mustStayOnScreen() {
+ return false;
+ }
+
/**
* A listener notifying when {@link #getActualHeight} changes.
*/
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/HeadsUpTouchHelper.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/HeadsUpTouchHelper.java
index b5b7f43..79c21f3 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/HeadsUpTouchHelper.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/HeadsUpTouchHelper.java
@@ -79,7 +79,8 @@
mTouchingHeadsUpView = false;
if (child instanceof ExpandableNotificationRow) {
mPickedChild = (ExpandableNotificationRow) child;
- mTouchingHeadsUpView = mPickedChild.isHeadsUp() && mPickedChild.isPinned();
+ mTouchingHeadsUpView = !mStackScroller.isExpanded()
+ && mPickedChild.isHeadsUp() && mPickedChild.isPinned();
}
break;
case MotionEvent.ACTION_POINTER_UP:
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 5f5974e..0febbd2 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java
@@ -738,9 +738,9 @@
+ (offscreen ? " OFFSCREEN!" : ""));
pw.println(String.format(" mCurrentView: id=%s (%dx%d) %s",
- getResourceName(mCurrentView.getId()),
- mCurrentView.getWidth(), mCurrentView.getHeight(),
- visibilityToString(mCurrentView.getVisibility())));
+ getResourceName(getCurrentView().getId()),
+ getCurrentView().getWidth(), getCurrentView().getHeight(),
+ visibilityToString(getCurrentView().getVisibility())));
pw.println(String.format(" disabled=0x%08x vertical=%s menu=%s",
mDisabledFlags,
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
index 09a7bf0..50a49a1 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
@@ -519,7 +519,7 @@
*/
protected boolean mStartedGoingToSleep;
- private static final int VISIBLE_LOCATIONS = StackViewState.LOCATION_FIRST_CARD
+ private static final int VISIBLE_LOCATIONS = StackViewState.LOCATION_FIRST_HUN
| StackViewState.LOCATION_MAIN_AREA;
private final OnChildLocationsChangedListener mNotificationLocationsChangedListener =
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 cc0e67d..49e9c3d 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java
@@ -75,7 +75,7 @@
ExpandableView.OnHeightChangedListener, NotificationGroupManager.OnGroupChangeListener {
public static final float BACKGROUND_ALPHA_DIMMED = 0.7f;
- private static final String TAG = "NotificationStackScrollLayout";
+ private static final String TAG = "StackScroller";
private static final boolean DEBUG = false;
private static final float RUBBER_BAND_FACTOR_NORMAL = 0.35f;
private static final float RUBBER_BAND_FACTOR_AFTER_EXPAND = 0.15f;
@@ -136,7 +136,7 @@
private StackScrollState mCurrentStackScrollState = new StackScrollState(this);
private AmbientState mAmbientState = new AmbientState();
private NotificationGroupManager mGroupManager;
- private ArrayList<View> mChildrenToAddAnimated = new ArrayList<>();
+ private HashSet<View> mChildrenToAddAnimated = new HashSet<>();
private ArrayList<View> mAddedHeadsUpChildren = new ArrayList<>();
private ArrayList<View> mChildrenToRemoveAnimated = new ArrayList<>();
private ArrayList<View> mSnappedBackChildren = new ArrayList<>();
@@ -474,6 +474,7 @@
* modifications to {@link #mOwnScrollY} are performed to reflect it in the view layout.
*/
private void updateChildren() {
+ updateScrollStateForAddedChildren();
mAmbientState.setScrollY(mOwnScrollY);
mStackScrollAlgorithm.getStackScrollState(mAmbientState, mCurrentStackScrollState);
if (!isCurrentlyAnimating() && !mNeedsAnimation) {
@@ -483,6 +484,28 @@
}
}
+ private void updateScrollStateForAddedChildren() {
+ if (mChildrenToAddAnimated.isEmpty()) {
+ return;
+ }
+ for (int i = 0; i < getChildCount(); i++) {
+ ExpandableView child = (ExpandableView) getChildAt(i);
+ if (mChildrenToAddAnimated.contains(child)) {
+ int startingPosition = getPositionInLinearLayout(child);
+ int padding = child.needsIncreasedPadding()
+ ? mIncreasedPaddingBetweenElements :
+ mPaddingBetweenElements;
+ int childHeight = getIntrinsicHeight(child) + padding;
+ if (startingPosition < mOwnScrollY) {
+ // This child starts off screen, so let's keep it offscreen to keep the others visible
+
+ mOwnScrollY += childHeight;
+ }
+ }
+ }
+ clampScrollPosition();
+ }
+
private void requestChildrenUpdate() {
if (!mChildrenUpdateRequested) {
getViewTreeObserver().addOnPreDrawListener(mChildrenUpdater);
@@ -1648,12 +1671,17 @@
bottom = (int) (lastView.getTranslationY() + lastView.getActualHeight());
bottom = Math.min(bottom, getHeight());
}
- } else if (mPhoneStatusBar.getBarState() == StatusBarState.KEYGUARD) {
- top = mTopPadding;
+ } else {
+ top = (int) (mTopPadding + mStackTranslation);
bottom = top;
}
- mBackgroundBounds.top = Math.max(0, top);
- mBackgroundBounds.bottom = Math.min(getHeight(), bottom);
+ if (mPhoneStatusBar.getBarState() != StatusBarState.KEYGUARD) {
+ mBackgroundBounds.top = (int) Math.max(mTopPadding + mStackTranslation, top);
+ } else {
+ // otherwise the animation from the shade to the keyguard will jump as it's maxed
+ mBackgroundBounds.top = Math.max(0, top);
+ }
+ mBackgroundBounds.bottom = Math.min(getHeight(), Math.max(bottom, top));
}
private ActivatableNotificationView getFirstPinnedHeadsUp() {
@@ -3206,6 +3234,10 @@
}
}
+ public boolean isExpanded() {
+ return mIsExpanded;
+ }
+
/**
* A listener that is notified when some child locations might have changed.
*/
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackScrollAlgorithm.java b/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackScrollAlgorithm.java
index f6959f0..e87b363 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackScrollAlgorithm.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackScrollAlgorithm.java
@@ -39,17 +39,14 @@
private static final String LOG_TAG = "StackScrollAlgorithm";
private static final int MAX_ITEMS_IN_BOTTOM_STACK = 3;
- private static final int MAX_ITEMS_IN_TOP_STACK = 3;
private int mPaddingBetweenElements;
private int mIncreasedPaddingBetweenElements;
private int mCollapsedSize;
- private int mTopStackPeekSize;
private int mBottomStackPeekSize;
private int mZDistanceBetweenElements;
private int mZBasicHeight;
- private StackIndentationFunctor mTopStackIndentationFunctor;
private StackIndentationFunctor mBottomStackIndentationFunctor;
private StackScrollAlgorithmState mTempAlgorithmState = new StackScrollAlgorithmState();
@@ -58,12 +55,8 @@
private boolean mIsExpanded;
private ExpandableView mFirstChildWhileExpanding;
private boolean mExpandedOnStart;
- private int mTopStackTotalSize;
private int mBottomStackSlowDownLength;
- private int mTopStackSlowDownLength;
private int mCollapseSecondCardPadding;
- private ExpandableView mFirstChild;
- private int mFirstChildMinHeight;
public StackScrollAlgorithm(Context context) {
initView(context);
@@ -71,22 +64,6 @@
public void initView(Context context) {
initConstants(context);
- updatePadding();
- }
-
- private void updatePadding() {
- mTopStackTotalSize = mTopStackSlowDownLength + mPaddingBetweenElements
- + mTopStackPeekSize;
- mTopStackIndentationFunctor = new PiecewiseLinearIndentationFunctor(
- MAX_ITEMS_IN_TOP_STACK,
- mTopStackPeekSize,
- mTopStackTotalSize - mTopStackPeekSize,
- 0.5f);
- mBottomStackIndentationFunctor = new PiecewiseLinearIndentationFunctor(
- MAX_ITEMS_IN_BOTTOM_STACK,
- mBottomStackPeekSize,
- getBottomStackSlowDownLength(),
- 0.5f);
}
public int getBottomStackSlowDownLength() {
@@ -100,8 +77,6 @@
.getDimensionPixelSize(R.dimen.notification_divider_height_increased);
mCollapsedSize = context.getResources()
.getDimensionPixelSize(R.dimen.notification_min_height);
- mTopStackPeekSize = context.getResources()
- .getDimensionPixelSize(R.dimen.top_stack_peek_amount);
mBottomStackPeekSize = context.getResources()
.getDimensionPixelSize(R.dimen.bottom_stack_peek_amount);
mZDistanceBetweenElements = Math.max(1, context.getResources()
@@ -109,10 +84,13 @@
mZBasicHeight = (MAX_ITEMS_IN_BOTTOM_STACK + 1) * mZDistanceBetweenElements;
mBottomStackSlowDownLength = context.getResources()
.getDimensionPixelSize(R.dimen.bottom_stack_slow_down_length);
- mTopStackSlowDownLength = context.getResources()
- .getDimensionPixelSize(R.dimen.top_stack_slow_down_length);
mCollapseSecondCardPadding = context.getResources().getDimensionPixelSize(
R.dimen.notification_collapse_second_card_padding);
+ mBottomStackIndentationFunctor = new PiecewiseLinearIndentationFunctor(
+ MAX_ITEMS_IN_BOTTOM_STACK,
+ mBottomStackPeekSize,
+ getBottomStackSlowDownLength(),
+ 0.5f);
}
public void getStackScrollState(AmbientState ambientState, StackScrollState resultState) {
@@ -123,32 +101,13 @@
// First we reset the view states to their default values.
resultState.resetViewStates();
- algorithmState.itemsInTopStack = 0.0f;
- algorithmState.partialInTop = 0.0f;
- algorithmState.lastTopStackIndex = 0;
- algorithmState.scrolledPixelsTop = 0;
- algorithmState.itemsInBottomStack = 0.0f;
- algorithmState.partialInBottom = 0.0f;
- mFirstChildMinHeight = mFirstChild == null ? 0 : mFirstChild.getMinHeight();
- float bottomOverScroll = ambientState.getOverScrollAmount(false /* onTop */);
+ initAlgorithmState(resultState, algorithmState, ambientState);
- int scrollY = ambientState.getScrollY();
-
- // Due to the overScroller, the stackscroller can have negative scroll state. This is
- // already accounted for by the top padding and doesn't need an additional adaption
- scrollY = Math.max(0, scrollY);
- algorithmState.scrollY = (int) (scrollY + mFirstChildMinHeight + bottomOverScroll);
-
- initAlgorithmState(resultState, algorithmState);
-
- // Phase 1:
- findNumberOfItemsInTopStackAndUpdateState(resultState, algorithmState, ambientState);
-
- // Phase 2:
updatePositionsForState(resultState, algorithmState, ambientState);
- // Phase 3:
- updateZValuesForState(resultState, algorithmState);
+ updateZValuesForState(resultState, algorithmState, ambientState);
+
+ updateHeadsUpStates(resultState, algorithmState, ambientState);
handleDraggedViews(ambientState, resultState, algorithmState);
updateDimmedActivatedHideSensitive(ambientState, resultState, algorithmState);
@@ -185,6 +144,7 @@
private void updateClipping(StackScrollState resultState,
StackScrollAlgorithmState algorithmState, AmbientState ambientState) {
boolean dismissAllInProgress = ambientState.isDismissAllInProgress();
+ float drawStart = ambientState.getTopPadding() + ambientState.getStackTranslation();
float previousNotificationEnd = 0;
float previousNotificationStart = 0;
boolean previousNotificationIsSwiped = false;
@@ -192,6 +152,10 @@
for (int i = 0; i < childCount; i++) {
ExpandableView child = algorithmState.visibleChildren.get(i);
StackViewState state = resultState.getViewStateForView(child);
+ if (!child.mustStayOnScreen()) {
+ previousNotificationEnd = Math.max(drawStart, previousNotificationEnd);
+ previousNotificationStart = Math.max(drawStart, previousNotificationStart);
+ }
float newYTranslation = state.yTranslation;
float newHeight = state.height;
// apply clipping and shadow
@@ -222,7 +186,7 @@
} else {
previousNotificationIsSwiped = ambientState.getDraggedViews().contains(child);
previousNotificationEnd = newNotificationEnd;
- previousNotificationStart = newYTranslation + state.clipTopAmount;
+ previousNotificationStart =newYTranslation + state.clipTopAmount;
}
}
}
@@ -314,8 +278,20 @@
/**
* Initialize the algorithm state like updating the visible children.
*/
- private void initAlgorithmState(StackScrollState resultState,
- StackScrollAlgorithmState state) {
+ private void initAlgorithmState(StackScrollState resultState, StackScrollAlgorithmState state,
+ AmbientState ambientState) {
+ state.itemsInBottomStack = 0.0f;
+ state.partialInBottom = 0.0f;
+ float bottomOverScroll = ambientState.getOverScrollAmount(false /* onTop */);
+
+ int scrollY = ambientState.getScrollY();
+
+ // Due to the overScroller, the stackscroller can have negative scroll state. This is
+ // already accounted for by the top padding and doesn't need an additional adaption
+ scrollY = Math.max(0, scrollY);
+ state.scrollY = (int) (scrollY + bottomOverScroll);
+
+ //now init the visible children and update paddings
ViewGroup hostView = resultState.getHostView();
int childCount = hostView.getChildCount();
state.visibleChildren.clear();
@@ -383,15 +359,9 @@
float bottomStackStart = bottomPeekStart - mBottomStackSlowDownLength;
// The y coordinate of the current child.
- float currentYPosition = 0.0f;
-
- // How far in is the element currently transitioning into the bottom stack.
- float yPositionInScrollView = 0.0f;
+ float currentYPosition = -algorithmState.scrollY;
int childCount = algorithmState.visibleChildren.size();
- int numberOfElementsCompletelyIn = algorithmState.partialInTop == 1.0f
- ? algorithmState.lastTopStackIndex
- : (int) algorithmState.itemsInTopStack;
int paddingAfterChild;
for (int i = 0; i < childCount; i++) {
ExpandableView child = algorithmState.visibleChildren.get(i);
@@ -400,47 +370,16 @@
paddingAfterChild = getPaddingAfterChild(algorithmState, child);
int childHeight = getMaxAllowedChildHeight(child);
int minHeight = child.getMinHeight();
- float yPositionInScrollViewAfterElement = yPositionInScrollView
- + childHeight
- + paddingAfterChild;
- float scrollOffset = yPositionInScrollView - algorithmState.scrollY +
- mFirstChildMinHeight;
-
- if (i == algorithmState.lastTopStackIndex + 1) {
- // Normally the position of this child is the position in the regular scrollview,
- // but if the two stacks are very close to each other,
- // then have have to push it even more upwards to the position of the bottom
- // stack start.
- currentYPosition = Math.min(scrollOffset, bottomStackStart);
- }
childViewState.yTranslation = currentYPosition;
+ if (i == 0) {
+ updateFirstChildHeight(child, childViewState, childHeight, ambientState);
+ }
// The y position after this element
float nextYPosition = currentYPosition + childHeight +
paddingAfterChild;
-
- if (i <= algorithmState.lastTopStackIndex) {
+ if (nextYPosition >= bottomStackStart) {
// Case 1:
- // We are in the top Stack
- updateStateForTopStackChild(algorithmState, child,
- numberOfElementsCompletelyIn, i, childHeight, childViewState, scrollOffset);
- clampPositionToTopStackEnd(childViewState, childHeight);
-
- // check if we are overlapping with the bottom stack
- if (childViewState.yTranslation + childHeight + paddingAfterChild
- >= bottomStackStart && !mIsExpansionChanging && i != 0) {
- // we just collapse this element slightly
- int newSize = (int) Math.max(bottomStackStart - paddingAfterChild -
- childViewState.yTranslation, minHeight);
- childViewState.height = newSize;
- updateStateForChildTransitioningInBottom(algorithmState, bottomStackStart,
- child, childViewState.yTranslation, childViewState,
- childHeight);
- }
- clampPositionToBottomStackStart(childViewState, childViewState.height,
- minHeight, ambientState);
- } else if (nextYPosition >= bottomStackStart) {
- // Case 2:
// We are in the bottom stack.
if (currentYPosition >= bottomStackStart) {
// According to the regular scroll view we are fully translated out of the
@@ -455,36 +394,30 @@
childViewState, childHeight);
}
} else {
- // Case 3:
+ // Case 2:
// We are in the regular scroll area.
childViewState.location = StackViewState.LOCATION_MAIN_AREA;
- clampYTranslation(childViewState, childHeight, ambientState);
+ clampPositionToBottomStackStart(childViewState, childViewState.height, childHeight,
+ ambientState);
}
- // The first card is always rendered.
- if (i == 0) {
- childViewState.hidden = false;
- childViewState.shadowAlpha = 1.0f;
- childViewState.yTranslation = Math.max(
- mFirstChildMinHeight - algorithmState.scrollY, 0);
- if (childViewState.yTranslation + childViewState.height
- > bottomPeekStart - mCollapseSecondCardPadding) {
- childViewState.height = (int) Math.max(
- bottomPeekStart - mCollapseSecondCardPadding
- - childViewState.yTranslation, mFirstChildMinHeight);
- }
- childViewState.location = StackViewState.LOCATION_FIRST_CARD;
+ if (i == 0 && ambientState.getScrollY() <= 0) {
+ // The first card can get into the bottom stack if it's the only one
+ // on the lockscreen which pushes it up. Let's make sure that doesn't happen and
+ // it stays at the top
+ childViewState.yTranslation = Math.max(0, childViewState.yTranslation);
+ }
+ currentYPosition = childViewState.yTranslation + childHeight + paddingAfterChild;
+ if (currentYPosition <= 0) {
+ childViewState.location = StackViewState.LOCATION_HIDDEN_TOP;
}
if (childViewState.location == StackViewState.LOCATION_UNKNOWN) {
Log.wtf(LOG_TAG, "Failed to assign location for child " + i);
}
- currentYPosition = childViewState.yTranslation + childHeight + paddingAfterChild;
- yPositionInScrollView = yPositionInScrollViewAfterElement;
childViewState.yTranslation += ambientState.getTopPadding()
+ ambientState.getStackTranslation();
}
- updateHeadsUpStates(resultState, algorithmState, ambientState);
}
private int getPaddingAfterChild(StackScrollAlgorithmState algorithmState,
@@ -506,24 +439,27 @@
ExpandableNotificationRow row = (ExpandableNotificationRow) child;
if (!row.isHeadsUp()) {
break;
- } else if (topHeadsUpEntry == null) {
- topHeadsUpEntry = row;
}
StackViewState childState = resultState.getViewStateForView(row);
+ if (topHeadsUpEntry == null) {
+ topHeadsUpEntry = row;
+ childState.location = StackViewState.LOCATION_FIRST_HUN;
+ }
boolean isTopEntry = topHeadsUpEntry == row;
+ float unmodifiedEndLocation = childState.yTranslation + childState.height;
if (mIsExpanded) {
- // Ensure that the heads up is always visible even when scrolled off from the bottom
- float bottomPosition = ambientState.getMaxHeadsUpTranslation() - childState.height;
- childState.yTranslation = Math.min(childState.yTranslation,
- bottomPosition);
+ // Ensure that the heads up is always visible even when scrolled off
+ clampHunToTop(ambientState, row, childState);
+ clampHunToMaxTranslation(ambientState, row, childState);
}
if (row.isPinned()) {
childState.yTranslation = Math.max(childState.yTranslation, 0);
childState.height = Math.max(row.getIntrinsicHeight(), childState.height);
- if (!isTopEntry) {
+ StackViewState topState = resultState.getViewStateForView(topHeadsUpEntry);
+ if (!isTopEntry && (!mIsExpanded
+ || unmodifiedEndLocation < topState.yTranslation + topState.height)) {
// Ensure that a headsUp doesn't vertically extend further than the heads-up at
// the top most z-position
- StackViewState topState = resultState.getViewStateForView(topHeadsUpEntry);
childState.height = row.getIntrinsicHeight();
childState.yTranslation = topState.yTranslation + topState.height
- childState.height;
@@ -532,17 +468,23 @@
}
}
- /**
- * Clamp the yTranslation both up and down to valid positions.
- *
- * @param childViewState the view state of the child
- * @param minHeight the minimum height of this child
- */
- private void clampYTranslation(StackViewState childViewState, int minHeight,
- AmbientState ambientState) {
- clampPositionToBottomStackStart(childViewState, childViewState.height, minHeight,
- ambientState);
- clampPositionToTopStackEnd(childViewState, childViewState.height);
+ private void clampHunToTop(AmbientState ambientState, ExpandableNotificationRow row,
+ StackViewState childState) {
+ float newTranslation = Math.max(ambientState.getTopPadding()
+ + ambientState.getStackTranslation(), childState.yTranslation);
+ childState.height = (int) Math.max(childState.height - (newTranslation
+ - childState.yTranslation), row.getMinHeight());
+ childState.yTranslation = newTranslation;
+ }
+
+ private void clampHunToMaxTranslation(AmbientState ambientState, ExpandableNotificationRow row,
+ StackViewState childState) {
+ float newTranslation;
+ float bottomPosition = ambientState.getMaxHeadsUpTranslation() - row.getMinHeight();
+ newTranslation = Math.min(childState.yTranslation, bottomPosition);
+ childState.height = (int) Math.max(childState.height
+ - (childState.yTranslation - newTranslation), row.getMinHeight());
+ childState.yTranslation = newTranslation;
}
/**
@@ -569,19 +511,6 @@
}
}
- /**
- * Clamp the yTranslation of the child up such that its end is at lest on the end of the top
- * stack.
- *
- * @param childViewState the view state of the child
- * @param childHeight the height of this child
- */
- private void clampPositionToTopStackEnd(StackViewState childViewState,
- int childHeight) {
- childViewState.yTranslation = Math.max(childViewState.yTranslation,
- mFirstChildMinHeight - childHeight);
- }
-
private int getMaxAllowedChildHeight(View child) {
if (child instanceof ExpandableView) {
ExpandableView expandableView = (ExpandableView) child;
@@ -611,9 +540,6 @@
}
childViewState.yTranslation = transitioningPositionStart + offset - newHeight
- getPaddingAfterChild(algorithmState, child);
-
- // We want at least to be at the end of the top stack when collapsing
- clampPositionToTopStackEnd(childViewState, newHeight);
childViewState.location = StackViewState.LOCATION_MAIN_AREA;
}
@@ -642,177 +568,59 @@
}
childViewState.height = minHeight;
childViewState.yTranslation = currentYPosition - minHeight;
- clampPositionToTopStackEnd(childViewState, minHeight);
}
- private void updateStateForTopStackChild(StackScrollAlgorithmState algorithmState,
- ExpandableView child, int numberOfElementsCompletelyIn, int i, int childHeight,
- StackViewState childViewState, float scrollOffset) {
-
-
- // First we calculate the index relative to the current stack window of size at most
- // {@link #MAX_ITEMS_IN_TOP_STACK}
- int paddedIndex = i - 1
- - Math.max(numberOfElementsCompletelyIn - MAX_ITEMS_IN_TOP_STACK, 0);
- if (paddedIndex >= 0) {
-
- // We are currently visually entering the top stack
- float distanceToStack = (childHeight + getPaddingAfterChild(algorithmState, child))
- - algorithmState.scrolledPixelsTop;
- if (i == algorithmState.lastTopStackIndex
- && distanceToStack > (mTopStackTotalSize
- + getPaddingAfterChild(algorithmState, child))) {
-
- // Child is currently translating into stack but not yet inside slow down zone.
- // Handle it like the regular scrollview.
- childViewState.yTranslation = scrollOffset;
- } else {
- // Apply stacking logic.
- float numItemsBefore;
- if (i == algorithmState.lastTopStackIndex) {
- numItemsBefore = 1.0f
- - (distanceToStack / (mTopStackTotalSize
- + getPaddingAfterChild(algorithmState, child)));
- } else {
- numItemsBefore = algorithmState.itemsInTopStack - i;
- }
- // The end position of the current child
- float currentChildEndY = mFirstChildMinHeight + mTopStackTotalSize
- - mTopStackIndentationFunctor.getValue(numItemsBefore);
- childViewState.yTranslation = currentChildEndY - childHeight;
- }
- childViewState.location = StackViewState.LOCATION_TOP_STACK_PEEKING;
- } else {
- if (paddedIndex == -1) {
- childViewState.shadowAlpha = 1.0f - algorithmState.partialInTop;
- } else {
- // We are hidden behind the top card and faded out, so we can hide ourselves.
- childViewState.hidden = true;
- childViewState.shadowAlpha = 0.0f;
- }
- childViewState.yTranslation = mFirstChildMinHeight - childHeight;
- childViewState.location = StackViewState.LOCATION_TOP_STACK_HIDDEN;
- }
-
-
- }
/**
- * Find the number of items in the top stack and update the result state if needed.
+ * Update the height of the first child i.e clamp it to the bottom stack
*
- * @param resultState The result state to update if a height change of an child occurs
- * @param algorithmState The state in which the current pass of the algorithm is currently in
+ *
+
+ * @param child the child to update
+ * @param childViewState the viewstate of the child
+ * @param childHeight the height of the child
+ * @param ambientState The ambient state of the algorithm
*/
- private void findNumberOfItemsInTopStackAndUpdateState(StackScrollState resultState,
- StackScrollAlgorithmState algorithmState, AmbientState ambientState) {
+ private void updateFirstChildHeight(ExpandableView child, StackViewState childViewState,
+ int childHeight, AmbientState ambientState) {
- // The y Position if the element would be in a regular scrollView
- float yPositionInScrollView = 0.0f;
- int childCount = algorithmState.visibleChildren.size();
- // find the number of elements in the top stack.
- for (int i = 0; i < childCount; i++) {
- ExpandableView child = algorithmState.visibleChildren.get(i);
- StackViewState childViewState = resultState.getViewStateForView(child);
- int childHeight = getMaxAllowedChildHeight(child);
- int paddingAfterChild = getPaddingAfterChild(algorithmState, child);
- float yPositionInScrollViewAfterElement = yPositionInScrollView
- + childHeight
- + paddingAfterChild;
- if (yPositionInScrollView < algorithmState.scrollY) {
- if (i == 0 && algorithmState.scrollY <= mFirstChildMinHeight) {
-
- // The starting position of the bottom stack peek
- int bottomPeekStart = ambientState.getInnerHeight() - mBottomStackPeekSize -
- mCollapseSecondCardPadding;
- // Collapse and expand the first child while the shade is being expanded
- float maxHeight = mIsExpansionChanging && child == mFirstChildWhileExpanding
- ? mFirstChildMaxHeight
- : childHeight;
- childViewState.height = (int) Math.max(Math.min(bottomPeekStart, maxHeight),
- mFirstChildMinHeight);
- algorithmState.itemsInTopStack = 1.0f;
-
- } else if (yPositionInScrollViewAfterElement < algorithmState.scrollY) {
- // According to the regular scroll view we are fully off screen
- algorithmState.itemsInTopStack += 1.0f;
- if (i == 0) {
- childViewState.height = child.getMinHeight();
- }
- } else {
- // According to the regular scroll view we are partially off screen
-
- // How much did we scroll into this child
- algorithmState.scrolledPixelsTop = algorithmState.scrollY
- - yPositionInScrollView;
- algorithmState.partialInTop = (algorithmState.scrolledPixelsTop) / (childHeight
- + paddingAfterChild);
-
- // Our element can be expanded, so this can get negative
- algorithmState.partialInTop = Math.max(0.0f, algorithmState.partialInTop);
- algorithmState.itemsInTopStack += algorithmState.partialInTop;
-
- if (i == 0) {
- // If it is expanded we have to collapse it to a new size
- float newSize = yPositionInScrollViewAfterElement
- - paddingAfterChild
- - algorithmState.scrollY + mFirstChildMinHeight;
- newSize = Math.max(mFirstChildMinHeight, newSize);
- algorithmState.itemsInTopStack = 1.0f;
- childViewState.height = (int) newSize;
- }
- algorithmState.lastTopStackIndex = i;
- break;
- }
- } else {
- algorithmState.lastTopStackIndex = i - 1;
- // We are already past the stack so we can end the loop
- break;
- }
- yPositionInScrollView = yPositionInScrollViewAfterElement;
- }
+ // The starting position of the bottom stack peek
+ int bottomPeekStart = ambientState.getInnerHeight() - mBottomStackPeekSize -
+ mCollapseSecondCardPadding + ambientState.getScrollY();
+ // Collapse and expand the first child while the shade is being expanded
+ float maxHeight = mIsExpansionChanging && child == mFirstChildWhileExpanding
+ ? mFirstChildMaxHeight
+ : childHeight;
+ childViewState.height = (int) Math.max(Math.min(bottomPeekStart, maxHeight),
+ child.getMinHeight());
}
/**
* Calculate the Z positions for all children based on the number of items in both stacks and
* save it in the resultState
- *
- * @param resultState The result state to update the zTranslation values
+ * @param resultState The result state to update the zTranslation values
* @param algorithmState The state in which the current pass of the algorithm is currently in
+ * @param ambientState The ambient state of the algorithm
*/
private void updateZValuesForState(StackScrollState resultState,
- StackScrollAlgorithmState algorithmState) {
+ StackScrollAlgorithmState algorithmState, AmbientState ambientState) {
int childCount = algorithmState.visibleChildren.size();
- for (int i = 0; i < childCount; i++) {
- View child = algorithmState.visibleChildren.get(i);
+ int childrenOnTop = 0;
+ for (int i = childCount - 1; i >= 0; i--) {
+ ExpandableView child = algorithmState.visibleChildren.get(i);
StackViewState childViewState = resultState.getViewStateForView(child);
- if (i < algorithmState.itemsInTopStack) {
- float stackIndex = algorithmState.itemsInTopStack - i;
-
- // Ensure that the topmost item is a little bit higher than the rest when fully
- // scrolled, to avoid drawing errors when swiping it out
- float max = MAX_ITEMS_IN_TOP_STACK + (i == 0 ? 2.5f : 2);
- stackIndex = Math.min(stackIndex, max);
- if (i == 0 && algorithmState.itemsInTopStack < 2.0f) {
-
- // We only have the top item and an additional item in the top stack,
- // Interpolate the index from 0 to 2 while the second item is
- // translating in.
- stackIndex -= 1.0f;
- if (algorithmState.scrollY > mFirstChildMinHeight) {
-
- // Since there is a shadow treshhold, we cant just interpolate from 0 to
- // 2 but we interpolate from 0.1f to 2.0f when scrolled in. The jump in
- // height will not be noticable since we have padding in between.
- stackIndex = 0.1f + stackIndex * 1.9f;
- }
- }
- childViewState.zTranslation = mZBasicHeight
- + stackIndex * mZDistanceBetweenElements;
- } else if (i > (childCount - 1 - algorithmState.itemsInBottomStack)) {
+ if (i > (childCount - 1 - algorithmState.itemsInBottomStack)) {
+ // We are in the bottom stack
float numItemsAbove = i - (childCount - 1 - algorithmState.itemsInBottomStack);
- float translationZ = mZBasicHeight
+ childViewState.zTranslation = mZBasicHeight
- numItemsAbove * mZDistanceBetweenElements;
- childViewState.zTranslation = translationZ;
+ } else if (child.mustStayOnScreen()
+ && childViewState.yTranslation < ambientState.getTopPadding()
+ + ambientState.getStackTranslation()) {
+ // TODO; do this more cleanly
+ childrenOnTop++;
+ childViewState.zTranslation = mZBasicHeight
+ + childrenOnTop * mZDistanceBetweenElements;
} else {
childViewState.zTranslation = mZBasicHeight;
}
@@ -897,7 +705,6 @@
}
public void notifyChildrenChanged(final NotificationStackScrollLayout hostView) {
- mFirstChild = hostView.getFirstChildNotGone();
if (mIsExpansionChanging) {
hostView.post(new Runnable() {
@Override
@@ -922,26 +729,6 @@
public int scrollY;
/**
- * The quantity of items which are in the top stack.
- */
- public float itemsInTopStack;
-
- /**
- * how far in is the element currently transitioning into the top stack
- */
- public float partialInTop;
-
- /**
- * The number of pixels the last child in the top stack has scrolled in to the stack
- */
- public float scrolledPixelsTop;
-
- /**
- * The last item index which is in the top stack.
- */
- public int lastTopStackIndex;
-
- /**
* The quantity of items which are in the bottom stack.
*/
public float itemsInBottomStack;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackViewState.java b/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackViewState.java
index 05fa27d..fa15195 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackViewState.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackViewState.java
@@ -24,12 +24,11 @@
// These are flags such that we can create masks for filtering.
public static final int LOCATION_UNKNOWN = 0x00;
- public static final int LOCATION_FIRST_CARD = 0x01;
- public static final int LOCATION_TOP_STACK_HIDDEN = 0x02;
- public static final int LOCATION_TOP_STACK_PEEKING = 0x04;
- public static final int LOCATION_MAIN_AREA = 0x08;
- public static final int LOCATION_BOTTOM_STACK_PEEKING = 0x10;
- public static final int LOCATION_BOTTOM_STACK_HIDDEN = 0x20;
+ public static final int LOCATION_FIRST_HUN = 0x01;
+ public static final int LOCATION_HIDDEN_TOP = 0x02;
+ public static final int LOCATION_MAIN_AREA = 0x04;
+ public static final int LOCATION_BOTTOM_STACK_PEEKING = 0x08;
+ public static final int LOCATION_BOTTOM_STACK_HIDDEN = 0x10;
/** The view isn't layouted at all. */
public static final int LOCATION_GONE = 0x40;
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index c8645b4..819250cf 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -8220,7 +8220,7 @@
*
* If {@code extractLibs} is true, native libraries are extracted from the app if required.
*/
- public void derivePackageAbi(PackageParser.Package pkg, File scanFile,
+ private void derivePackageAbi(PackageParser.Package pkg, File scanFile,
String cpuAbiOverride, boolean extractLibs)
throws PackageManagerException {
// TODO: We can probably be smarter about this stuff. For installed apps,
@@ -8301,16 +8301,17 @@
if (abi32 >= 0) {
final String abi = Build.SUPPORTED_32_BIT_ABIS[abi32];
if (abi64 >= 0) {
- pkg.applicationInfo.secondaryCpuAbi = abi;
+ if (cpuAbiOverride == null && pkg.use32bitAbi) {
+ pkg.applicationInfo.secondaryCpuAbi = pkg.applicationInfo.primaryCpuAbi;
+ pkg.applicationInfo.primaryCpuAbi = abi;
+ } else {
+ pkg.applicationInfo.secondaryCpuAbi = abi;
+ }
} else {
pkg.applicationInfo.primaryCpuAbi = abi;
}
}
- if (cpuAbiOverride != null &&
- cpuAbiOverride.equals(pkg.applicationInfo.secondaryCpuAbi)) {
- pkg.applicationInfo.secondaryCpuAbi = pkg.applicationInfo.primaryCpuAbi;
- pkg.applicationInfo.primaryCpuAbi = cpuAbiOverride;
- }
+
} else {
String[] abiList = (cpuAbiOverride != null) ?
new String[] { cpuAbiOverride } : Build.SUPPORTED_ABIS;
diff --git a/telecomm/java/android/telecom/TelecomManager.java b/telecomm/java/android/telecom/TelecomManager.java
index c122c5a..f1cbb9a 100644
--- a/telecomm/java/android/telecom/TelecomManager.java
+++ b/telecomm/java/android/telecom/TelecomManager.java
@@ -774,9 +774,9 @@
}
/**
- * Register a {@link PhoneAccount} for use by the system. When registering
- * {@link PhoneAccount}s, existing registrations will be overwritten if the
- * {@link PhoneAccountHandle} matches that of a {@link PhoneAccount} which is already
+ * Register a {@link PhoneAccount} for use by the system that will be stored in Device Encrypted
+ * storage. When registering {@link PhoneAccount}s, existing registrations will be overwritten
+ * if the {@link PhoneAccountHandle} matches that of a {@link PhoneAccount} which is already
* registered. Once registered, the {@link PhoneAccount} is listed to the user as an option
* when placing calls. The user may still need to enable the {@link PhoneAccount} within
* the phone app settings before the account is usable.
@@ -1166,11 +1166,16 @@
/**
* Registers a new incoming call. A {@link ConnectionService} should invoke this method when it
* has an incoming call. The specified {@link PhoneAccountHandle} must have been registered
- * with {@link #registerPhoneAccount}. Once invoked, this method will cause the system to bind
- * to the {@link ConnectionService} associated with the {@link PhoneAccountHandle} and request
- * additional information about the call (See
- * {@link ConnectionService#onCreateIncomingConnection}) before starting the incoming call UI.
- *
+ * with {@link #registerPhoneAccount} and the user must have enabled the corresponding
+ * {@link PhoneAccount}. This can be checked using {@link #getPhoneAccount}. Once invoked, this
+ * method will cause the system to bind to the {@link ConnectionService} associated with the
+ * {@link PhoneAccountHandle} and request additional information about the call
+ * (See {@link ConnectionService#onCreateIncomingConnection}) before starting the incoming
+ * call UI.
+ * <p>
+ * A {@link SecurityException} will be thrown if either the {@link PhoneAccountHandle} does not
+ * correspond to a registered {@link PhoneAccount} or the associated {@link PhoneAccount} is not
+ * currently enabled by the user.
* @param phoneAccount A {@link PhoneAccountHandle} registered with
* {@link #registerPhoneAccount}.
* @param extras A bundle that will be passed through to
diff --git a/wifi/java/android/net/wifi/ScanResult.java b/wifi/java/android/net/wifi/ScanResult.java
index 4a86c59..31da670 100644
--- a/wifi/java/android/net/wifi/ScanResult.java
+++ b/wifi/java/android/net/wifi/ScanResult.java
@@ -332,6 +332,7 @@
public static class InformationElement {
public static final int EID_SSID = 0;
public static final int EID_BSS_LOAD = 11;
+ public static final int EID_RSN = 48;
public static final int EID_HT_OPERATION = 61;
public static final int EID_INTERWORKING = 107;
public static final int EID_ROAMING_CONSORTIUM = 111;
diff --git a/wifi/java/android/net/wifi/WifiEnterpriseConfig.java b/wifi/java/android/net/wifi/WifiEnterpriseConfig.java
index a0dbd85..362738e 100644
--- a/wifi/java/android/net/wifi/WifiEnterpriseConfig.java
+++ b/wifi/java/android/net/wifi/WifiEnterpriseConfig.java
@@ -101,6 +101,8 @@
/** @hide */
public static final String CA_CERT_KEY = "ca_cert";
/** @hide */
+ public static final String CA_PATH_KEY = "ca_path";
+ /** @hide */
public static final String ENGINE_KEY = "engine";
/** @hide */
public static final String ENGINE_ID_KEY = "engine_id";
@@ -625,6 +627,33 @@
mCaCerts = null;
}
+ /**
+ * Set the ca_path directive on wpa_supplicant.
+ *
+ * From wpa_supplicant documentation:
+ *
+ * Directory path for CA certificate files (PEM). This path may contain
+ * multiple CA certificates in OpenSSL format. Common use for this is to
+ * point to system trusted CA list which is often installed into directory
+ * like /etc/ssl/certs. If configured, these certificates are added to the
+ * list of trusted CAs. ca_cert may also be included in that case, but it is
+ * not required.
+ * @param domain The path for CA certificate files
+ * @hide
+ */
+ public void setCaPath(String path) {
+ setFieldValue(CA_PATH_KEY, path);
+ }
+
+ /**
+ * Get the domain_suffix_match value. See setDomSuffixMatch.
+ * @return The path for CA certificate files.
+ * @hide
+ */
+ public String getCaPath() {
+ return getFieldValue(CA_PATH_KEY, "");
+ }
+
/** Set Client certificate alias.
*
* <p> See the {@link android.security.KeyChain} for details on installing or choosing